aboutsummaryrefslogtreecommitdiff
path: root/nuttx/arch
diff options
context:
space:
mode:
authorpx4dev <px4@purgatory.org>2012-08-04 15:12:36 -0700
committerpx4dev <px4@purgatory.org>2012-08-04 15:12:36 -0700
commit8a365179eafdf3aea98e60ab9f5882b200d4c759 (patch)
tree4f38d6d4cd80bd0b6e22e2bb534c3f117ce44e56 /nuttx/arch
downloadpx4-firmware-8a365179eafdf3aea98e60ab9f5882b200d4c759.tar.gz
px4-firmware-8a365179eafdf3aea98e60ab9f5882b200d4c759.tar.bz2
px4-firmware-8a365179eafdf3aea98e60ab9f5882b200d4c759.zip
Fresh import of the PX4 firmware sources.
Diffstat (limited to 'nuttx/arch')
-rw-r--r--nuttx/arch/Kconfig92
-rw-r--r--nuttx/arch/README.txt339
-rw-r--r--nuttx/arch/arm/Kconfig206
-rw-r--r--nuttx/arch/arm/include/arch.h122
-rw-r--r--nuttx/arch/arm/include/arm/irq.h231
-rw-r--r--nuttx/arch/arm/include/arm/syscall.h243
-rw-r--r--nuttx/arch/arm/include/armv7-m/irq.h306
-rw-r--r--nuttx/arch/arm/include/armv7-m/irq_cmnvector.h164
-rw-r--r--nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h182
-rw-r--r--nuttx/arch/arm/include/armv7-m/syscall.h243
-rw-r--r--nuttx/arch/arm/include/irq.h100
-rw-r--r--nuttx/arch/arm/include/limits.h81
-rw-r--r--nuttx/arch/arm/include/math.h608
-rw-r--r--nuttx/arch/arm/include/serial.h58
-rw-r--r--nuttx/arch/arm/include/stdarg.h59
-rw-r--r--nuttx/arch/arm/include/stm32/chip.h550
-rw-r--r--nuttx/arch/arm/include/stm32/irq.h117
-rw-r--r--nuttx/arch/arm/include/stm32/stm32f10xxx_irq.h281
-rw-r--r--nuttx/arch/arm/include/stm32/stm32f20xxx_irq.h182
-rw-r--r--nuttx/arch/arm/include/stm32/stm32f40xxx_irq.h185
-rw-r--r--nuttx/arch/arm/include/syscall.h90
-rw-r--r--nuttx/arch/arm/include/types.h101
-rw-r--r--nuttx/arch/arm/include/watchdog.h61
-rw-r--r--nuttx/arch/arm/src/Makefile162
-rw-r--r--nuttx/arch/arm/src/arm/arm.h451
-rw-r--r--nuttx/arch/arm/src/arm/pg_macros.h522
-rwxr-xr-xnuttx/arch/arm/src/arm/up_allocpage.c243
-rw-r--r--nuttx/arch/arm/src/arm/up_assert.c325
-rwxr-xr-xnuttx/arch/arm/src/arm/up_blocktask.c167
-rw-r--r--nuttx/arch/arm/src/arm/up_cache.S74
-rwxr-xr-xnuttx/arch/arm/src/arm/up_checkmapping.c123
-rw-r--r--nuttx/arch/arm/src/arm/up_copystate.c82
-rw-r--r--nuttx/arch/arm/src/arm/up_dataabort.c201
-rw-r--r--nuttx/arch/arm/src/arm/up_doirq.c114
-rw-r--r--nuttx/arch/arm/src/arm/up_fullcontextrestore.S118
-rw-r--r--nuttx/arch/arm/src/arm/up_head.S638
-rw-r--r--nuttx/arch/arm/src/arm/up_initialstate.c146
-rw-r--r--nuttx/arch/arm/src/arm/up_nommuhead.S167
-rwxr-xr-xnuttx/arch/arm/src/arm/up_pginitialize.c96
-rw-r--r--nuttx/arch/arm/src/arm/up_prefetchabort.c154
-rwxr-xr-xnuttx/arch/arm/src/arm/up_releasepending.c132
-rwxr-xr-xnuttx/arch/arm/src/arm/up_reprioritizertr.c187
-rw-r--r--nuttx/arch/arm/src/arm/up_saveusercontext.S119
-rw-r--r--nuttx/arch/arm/src/arm/up_schedulesigaction.c204
-rw-r--r--nuttx/arch/arm/src/arm/up_sigdeliver.c139
-rw-r--r--nuttx/arch/arm/src/arm/up_syscall.c96
-rwxr-xr-xnuttx/arch/arm/src/arm/up_unblocktask.c159
-rw-r--r--nuttx/arch/arm/src/arm/up_undefinedinsn.c81
-rwxr-xr-xnuttx/arch/arm/src/arm/up_va2pte.c121
-rw-r--r--nuttx/arch/arm/src/arm/up_vectoraddrexcptn.S83
-rw-r--r--nuttx/arch/arm/src/arm/up_vectors.S446
-rw-r--r--nuttx/arch/arm/src/arm/up_vectortab.S103
-rw-r--r--nuttx/arch/arm/src/armv7-m/exc_return.h117
-rw-r--r--nuttx/arch/arm/src/armv7-m/memcpy.S351
-rw-r--r--nuttx/arch/arm/src/armv7-m/mpu.h509
-rw-r--r--nuttx/arch/arm/src/armv7-m/nvic.h531
-rw-r--r--nuttx/arch/arm/src/armv7-m/psr.h87
-rw-r--r--nuttx/arch/arm/src/armv7-m/svcall.h94
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_assert.c334
-rwxr-xr-xnuttx/arch/arm/src/armv7-m/up_blocktask.c167
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_copystate.c86
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_doirq.c123
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_exception.S237
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_fpu.S286
-rwxr-xr-xnuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S95
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_hardfault.c144
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_initialstate.c200
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_memfault.c110
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_mpu.c176
-rwxr-xr-xnuttx/arch/arm/src/armv7-m/up_releasepending.c129
-rwxr-xr-xnuttx/arch/arm/src/armv7-m/up_reprioritizertr.c182
-rwxr-xr-xnuttx/arch/arm/src/armv7-m/up_saveusercontext.S104
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c208
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_sigdeliver.c142
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_stackcheck.c40
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_svcall.c363
-rwxr-xr-xnuttx/arch/arm/src/armv7-m/up_switchcontext.S97
-rwxr-xr-xnuttx/arch/arm/src/armv7-m/up_unblocktask.c157
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_vectors.c95
-rw-r--r--nuttx/arch/arm/src/common/up_allocateheap.c83
-rw-r--r--nuttx/arch/arm/src/common/up_arch.h105
-rw-r--r--nuttx/arch/arm/src/common/up_checkstack.c147
-rw-r--r--nuttx/arch/arm/src/common/up_createstack.c197
-rwxr-xr-xnuttx/arch/arm/src/common/up_etherstub.c86
-rw-r--r--nuttx/arch/arm/src/common/up_exit.c174
-rw-r--r--nuttx/arch/arm/src/common/up_idle.c91
-rw-r--r--nuttx/arch/arm/src/common/up_initialize.c191
-rw-r--r--nuttx/arch/arm/src/common/up_internal.h393
-rw-r--r--nuttx/arch/arm/src/common/up_interruptcontext.c70
-rw-r--r--nuttx/arch/arm/src/common/up_lowputs.c74
-rw-r--r--nuttx/arch/arm/src/common/up_mdelay.c90
-rw-r--r--nuttx/arch/arm/src/common/up_modifyreg16.c85
-rw-r--r--nuttx/arch/arm/src/common/up_modifyreg32.c85
-rw-r--r--nuttx/arch/arm/src/common/up_modifyreg8.c85
-rw-r--r--nuttx/arch/arm/src/common/up_puts.c75
-rw-r--r--nuttx/arch/arm/src/common/up_releasestack.c79
-rw-r--r--nuttx/arch/arm/src/common/up_udelay.c129
-rw-r--r--nuttx/arch/arm/src/common/up_usestack.c155
-rw-r--r--nuttx/arch/arm/src/stm32/Kconfig1912
-rw-r--r--nuttx/arch/arm/src/stm32/Make.defs143
-rw-r--r--nuttx/arch/arm/src/stm32/chip.h100
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_adc.h564
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_bkp.h190
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_can.h505
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_dac.h256
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_dbgmcu.h144
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_eth.h829
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_exti.h141
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_flash.h190
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_i2c.h192
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_memorymap.h57
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_otgfs.h1002
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_pwr.h103
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_sdio.h291
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_spi.h205
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_syscfg.h151
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_tim.h1029
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_uart.h229
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_usbdev.h236
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_wdg.h145
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f100_pinmap.h267
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f103re_pinmap.h332
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f103vc_pinmap.h423
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h583
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f105vb_pinmap.h416
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f107vc_pinmap.h416
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f10xxx_dma.h350
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f10xxx_gpio.h364
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f10xxx_memorymap.h136
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rcc.h328
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rtc.h96
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f10xxx_vectors.h214
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f20xxx_dma.h520
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f20xxx_gpio.h370
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f20xxx_memorymap.h197
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f20xxx_pinmap.h695
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h504
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rtc.h338
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f20xxx_vectors.h141
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f40xxx_dma.h520
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f40xxx_gpio.h370
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f40xxx_memorymap.h197
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h695
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h506
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h338
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32f40xxx_vectors.h142
-rw-r--r--nuttx/arch/arm/src/stm32/stm32.h103
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_adc.c1780
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_adc.h596
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_allocateheap.c323
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_bkp.h52
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_can.c1636
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_can.h145
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_dac.c860
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_dac.h139
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_dbgmcu.h64
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_dma.c80
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_dma.h309
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_dumpgpio.c179
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_eth.c3109
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_eth.h97
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_exti.h119
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_exti_alarm.c167
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_exti_gpio.c337
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_flash.c247
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_flash.h49
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_fsmc.h304
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_gpio.c736
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_gpio.h514
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_i2c.c2137
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_i2c.h50
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_idle.c188
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_internal.h45
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_irq.c476
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_iwdg.c711
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_lowputc.c428
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_lowputc.h79
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_lse.c105
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_lsi.c100
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_otgfs.h93
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_otgfsdev.c5413
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pm.h142
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pminitialize.c94
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pmsleep.c117
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pmstandby.c109
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pmstop.c122
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pwm.c1525
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pwm.h370
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pwr.c98
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_pwr.h89
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_qencoder.c1228
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_qencoder.h142
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_rcc.c183
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_rcc.h239
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_rtc.c80
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_rtc.h85
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_sdio.c2842
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_sdio.h127
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_serial.c1959
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_spi.c1396
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_spi.h121
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_start.c240
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_syscfg.h104
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_tim.c1020
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_tim.h191
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_timerisr.c164
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_uart.h254
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_usbdev.c3664
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_usbdev.h98
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_usbhost.c2695
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_usbhost.h71
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_vectors.S421
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_waste.c57
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_waste.h78
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_wdg.h118
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_wwdg.c807
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c615
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c556
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c685
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f20xxx_dma.c903
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c666
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f20xxx_rtc.c842
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c903
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c668
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c842
225 files changed, 85384 insertions, 0 deletions
diff --git a/nuttx/arch/Kconfig b/nuttx/arch/Kconfig
new file mode 100644
index 000000000..253151a3b
--- /dev/null
+++ b/nuttx/arch/Kconfig
@@ -0,0 +1,92 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+choice
+ prompt "CPU Architecture"
+ default ARCH_ARM
+
+config ARCH_8051
+ bool "8051"
+ ---help---
+ Intel 8051 architectures and derivaties
+
+config ARCH_ARM
+ bool "ARM"
+ ---help---
+ The ARM architectures
+
+config ARCH_AVR
+ bool "AVR"
+ ---help---
+ Atmel 9-bit bit AVR and 32-bit AVR32 architectures
+
+config ARCH_HC
+ bool "Freescale HC"
+ ---help---
+ Freescale HC architectures (M9S12)
+
+config ARCH_MIPS
+ bool "MIPS"
+ ---help---
+ MIPS architectures (PIC32)
+
+config ARCH_RGMP
+ bool "RGMP"
+ ---help---
+ RTOS and GPOS on Multi-Processor (RGMP) architecture. See
+ http://rgmp.sourceforge.net/wiki/index.php/Main_Page.
+
+config ARCH_SH
+ bool "Rensas"
+ ---help---
+ Renesas architectures (SH and M16C).
+
+config ARCH_SIM
+ bool "Simulation"
+ ---help---
+ Linux/Cywgin user-mode simulation.
+
+config ARCH_X86
+ bool "x86"
+ ---help---
+ Intel x86 architectures.
+
+config ARCH_Z16
+ bool "ZNEO"
+ ---help---
+ ZiLOG ZNEO 16-bit architectures (z16f).
+
+config ARCH_Z80
+ bool "z80"
+ ---help---
+ ZiLOG 8-bit architectures (z80, ez80, z8).
+
+endchoice
+
+config ARCH
+ string
+ default "8051" if ARCH_8051
+ default "arm" if ARCH_ARM
+ default "avr" if ARCH_AVR
+ default "hc" if ARCH_HC
+ default "mips" if ARCH_MIPS
+ default "rgmp" if ARCH_RGMP
+ default "sh" if ARCH_SH
+ default "sim" if ARCH_SIM
+ default "x86" if ARCH_X86
+ default "z16" if ARCH_Z16
+ default "z80" if ARCH_Z80
+
+source arch/8051/Kconfig
+source arch/arm/Kconfig
+source arch/avr/Kconfig
+source arch/hc/Kconfig
+source arch/mips/Kconfig
+source arch/rgmp/Kconfig
+source arch/sh/Kconfig
+source arch/sim/Kconfig
+source arch/x86/Kconfig
+source arch/z16/Kconfig
+source arch/z80/Kconfig
diff --git a/nuttx/arch/README.txt b/nuttx/arch/README.txt
new file mode 100644
index 000000000..67b99b255
--- /dev/null
+++ b/nuttx/arch/README.txt
@@ -0,0 +1,339 @@
+Architecture-Specific Code
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+Table of Contents
+^^^^^^^^^^^^^^^^^
+
+ o Architecture-Specific Code
+ o Summary of Files
+ o Supported Architectures
+ o Configuring NuttX
+
+Architecture-Specific Code
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The NuttX configuration consists of:
+
+o Processor architecture specific files. These are the files contained
+ in the arch/<arch-name>/ directory discussed in this README.
+
+o Chip/SoC specific files. Each processor processor architecture
+ is embedded in chip or System-on-a-Chip (SoC) architecture. The
+ full chip architecture includes the processor architecture plus
+ chip-specific interrupt logic, general purpose I/O (GIO) logic, and
+ specialized, internal peripherals (such as UARTs, USB, etc.).
+
+ These chip-specific files are contained within chip-specific
+ sub-directories in the arch/<arch-name>/ directory and are selected
+ via the CONFIG_ARCH_name selection
+
+o Board specific files. In order to be usable, the chip must be
+ contained in a board environment. The board configuration defines
+ additional properties of the board including such things as
+ peripheral LEDs, external peripherals (such as network, USB, etc.).
+
+ These board-specific configuration files can be found in the
+ configs/<board-name>/ sub-directories.
+
+This README will address the processor architecture specific files
+that are contained in the arch/<arch-name>/ directory. The file
+include/nuttx/arch.h identifies all of the APIs that must
+be provided by this architecture specific logic. (It also includes
+arch/<arch-name>/arch.h as described below).
+
+Directory Structure
+^^^^^^^^^^^^^^^^^^^
+
+The arch directory contains architecture specific logic. The complete
+board port in is defined by the architecture-specific code in this
+directory (plus the board-specific configurations in the config/
+subdirectory). Each architecture must provide a subdirectory <arch-name>
+under arch/ with the following characteristics:
+
+
+ <arch-name>/
+ |-- include/
+ | |--<chip-name>/
+ | | `-- (chip-specific header files)
+ | |--<other-chips>/
+ | |-- arch.h
+ | |-- irq.h
+ | `-- types.h
+ `-- src/
+ |--<chip-name>/
+ | `-- (chip-specific source files)
+ |--<other-chips>/
+ |-- Makefile
+ `-- (architecture-specific source files)
+
+Summary of Files
+^^^^^^^^^^^^^^^^
+
+include/<chip-name>/
+ This sub-directory contains chip-specific header files.
+
+include/arch.h
+ This is a hook for any architecture specific definitions that may
+ be needed by the system. It is included by include/nuttx/arch.h
+
+include/types.h
+ This provides architecture/toolchain-specific definitions for
+ standard types. This file should typedef:
+
+ _int8_t, _uint8_t, _int16_t, _uint16_t, _int32_t, _uint32_t
+
+ and if the architecture supports 64-bit integers.
+
+ _int24_t, _uint24_t, int64_t, uint64_t
+
+ NOTE that these type names have a leading underscore character. This
+ file will be included(indirectly) by include/stdint.h and typedef'ed to
+ the final name without the underscore character. This roundabout way of
+ doings things allows the stdint.h to be removed from the include/
+ directory in the event that the user prefers to use the definitions
+ provided by their toolchain header files
+
+ irqstate_t
+
+ Must be defined to the be the size required to hold the interrupt
+ enable/disable state.
+
+ This file will be included by include/sys/types.h and be made
+ available to all files.
+
+include/irq.h
+ This file needs to define some architecture specific functions (usually
+ inline if the compiler supports inlining) and structure. These include:
+
+ - struct xcptcontext. This structures represents the saved context
+ of a thread.
+
+ - irqstate_t irqsave(void) -- Used to disable all interrupts.
+
+ - void irqrestore(irqstate_t flags) -- Used to restore interrupt
+ enables to the same state as before irqsave was called.
+
+ This file must also define NR_IRQS, the total number of IRQs supported
+ by the board.
+
+src/<chip-name>/
+ This sub-directory contains chip-specific source files.
+
+src/Makefile
+ This makefile will be executed to build the targets src/libup.a and
+ src/up_head.o. The up_head.o file holds the entry point into the system
+ (power-on reset entry point, for example). It will be used in
+ the final link with libup.a and other system archives to generate the
+ final executable.
+
+Supported Architectures
+^^^^^^^^^^^^^^^^^^^^^^^
+
+arch/sim - Linux/Cygwin simulation
+ A user-mode port of NuttX to the x86 Linux platform is available.
+ The purpose of this port is primarily to support OS feature development.
+ This port does not support interrupts or a real timer (and hence no
+ round robin scheduler) Otherwise, it is complete.
+
+arch/arm - ARM-based micro-controllers
+ This directory holds common ARM architectures. At present, this includes
+ the following subdirectories:
+
+ arch/arm/include and arch/arm/src/common
+ Common ARM/Cortex-M3 logic.
+
+ arch/arm/src/arm and arch/arm/include/arm
+ Common ARM-specific logic
+
+ arch/arm/src/armv7-m and arch/arm/include/armv7-m
+ Common ARMv7-M logic (Cortex-M3 and Cortex-M4)
+
+ arch/arm/include/c5471 and arch/arm/src/c5471
+ TI TMS320C5471 (also called TMS320DM180 or just C5471).
+ NuttX operates on the ARM7 of this dual core processor. This port
+ complete, verified, and included in the NuttX release 0.1.1.
+
+ arch/arm/include/calypso and arch/arm/src/calypso
+ TI "Calypso" MCU used in various cell phones (and, in particular,
+ by the Osmocom-bb project). Like the c5471, NuttX operates on the
+ ARM7 of this dual core processor. This port was contributed by
+ Denis Carilki and includes the work of Denis, Alan Carvalho de Assis,
+ and Stefan Richter. Calypso support first appeared in NuttX-6.17.
+
+ arch/arm/include/dm320 and arch/arm/src/dm320
+ TI TMS320DM320 (also called just DM320).
+ NuttX operates on the ARM9EJS of this dual core processor. This port
+ complete, verified, and included in the NuttX release 0.2.1.
+
+ arch/arm/include/imx and arch/arm/src/imx
+ Freescale MC9328MX1 or i.MX1. This port uses the Freescale MX1ADS
+ development board with a GNU arm-elf toolchain* under either Linux or Cygwin.
+ STATUS: This port has stalled because of development tool issues. Coding
+ is complete on the basic port (timer, serial console, SPI).
+
+ arch/arm/include/lm3s and arch/arm/src/lm3s
+ These directories contain support for the Luminary LMS family, particularly
+ for the LM3S6918. The initial, release of this port was included in NuttX version
+ 0.4.6. The current port includes timer, serial console, Ethernet, SSI, and microSD
+ support. There are working configurations the NuttX OS test, to run the NuttShell
+ (NSH), the NuttX networking test, and the uIP web server.
+
+ arch/arm/include/lpc214x and arch/arm/src/lpc214x
+ These directories provide support for NXP LPC214x family of
+ ARM7TDMI processors. This port boots and passes the OS test (examples/ostest).
+ The port is complete and verifed. As of NuttX 0.3.17, the port includes:
+ timer interrupts, serial console, USB driver, and SPI-based MMC/SD card
+ support. A verifed NuttShell (NSH) configuration is also available.
+
+ arch/arm/include/lpc2378 and arch/arm/src/lpc2378.
+ NXP LPC2378. Support is provided for the NXP LPC2378 MCU. This port was
+ contributed by Rommel Marcelo is was first released in NuttX-5.3.
+ STATUS: This port boots and passes the OS test (examples/ostest) and
+ includes a working implementation of the NuttShell (NSH). The port is
+ complete and verified. As of NuttX 5.3, the port includes only basic
+ timer interrupts and serial console support.
+
+ arch/arm/include/lpc31xx and arch/arm/src/lpc31xx
+ These directories provide support for NXP LPC31xx family of
+ ARM926EJ-S processors. The port for the NXP LPC3131 was first
+ released in NuttX-5.1 (but was not functional until NuttX-5.2).
+ STATUS: The basic EA3131 port is complete and verified in NuttX-5.2
+ This basic port includes basic boot-up, serial console, and timer
+ interrupts. This port was extended in NuttX 5.3 with a USB high
+ speed driver contributed by David Hewson. This port has been
+ verified using the NuttX OS test, USB serial and mass storage tests
+ and includes a working implementation of the NuttShell ((NSH)).
+
+ This port was later extended to support additional members of the
+ LPC31xx family including, specifically, the LPC3152.
+
+ arch/arm/include/sam3u and arch/arm/src/sam3u
+ Atmel AT91SAM3U. This port is for Atmel AT91SAM3U4E MCU.
+ STATUS: The basic AT91SAM3U port was released in NuttX version 5.1.
+ The basic port includes boot-up logic, interrupt driven serial
+ console, and system timer interrupts. That release passes the
+ NuttX OS test and is proven to have a valid OS implementation. A
+ onfiguration to support the NuttShell is also included.
+
+ arch/arm/include/stm32 and arch/arm/src/stm32
+ These directories contain support for the STMicro STM32 F1, F2, and
+ F4 families.
+
+ STATUS: The basic STM32 F1 port was released in NuttX version 0.4.12.
+ and has continued to develop consistently over time. It now includes
+ support for the F2 and F4 families and a rich offering of peripheral
+ drivers.
+
+ arch/arm/include/str71x and arch/arm/src/str71x
+ These directories provide support for the STMicro STR71x processors.
+ Coding is complete on the basic port (boot logic, system time, serial console),
+ but no testing has been performed due to some problems I am having with my
+ JTAG wiggler and OpenOCD on Linux.
+
+arch/avr
+ This directory is dedicated to ports to the Atmel AVR (8-bit) and AVR32 (32-bit)
+ MCU families. STATUS: Under development.
+
+ arch/avr/include/avr and arch/avr/src/avr
+ Common support for all 8-bit VR MCUs
+
+ arch/avr/include/atmega and arch/avr/src/atmega
+ Support specifically for the AVR ATMega family (specifically only for
+ the ATMega128 at the moment).
+
+ arch/avr/include/at90usb and arch/avr/src/at90usb
+ Support specifically for the AVR AT90USB646, 647, 1286, and 1287 family.
+
+ arch/avr/include/avr32 and arch/avr/src/avr32
+ Common support for all AVR32 MCUs
+
+ arch/avr/include/at32uc3 and arch/avr/src/at32uc3
+ Support specifically for the AT32UC3Bxxx family (specifically only for
+ the AT32UC3B0256 at the moment).
+
+arch/hc
+ This directory is dedicated to ports to the Freescale HC family.
+
+ arch/arm/include/m9s12 and arch/arm/src/m9s12
+ These directories provide support for the Freescale mc9s12x family.
+ STATUS: Fragments of this port were first released in nuttx-5.0 and
+ the port was "code-complete" as nuttx-5.18. However, the final
+ verification effort has been stalled because of higher priority tasks.
+
+arch/m68322
+ A work in progress.
+ STATUS: Stalled for the time being.
+
+arch/mips
+ This directory is dedicated to ports to the MIPS family.
+
+ arch/mips/include/mips32 and arch/mips/src/mips32
+ Common support for all MIPS32 architectures
+
+ arch/mips/include/pic32mx and arch/mips/src/pic32mx
+ Support for all MicroChip PIC32MX architectures
+
+arch/rgmp
+
+ RGMP stands for RTOS and GPOS on Multi-Processor. RGMP is a project
+ for running GPOS and RTOS simultaneously on multi-processor platforms.
+ You can port your favorite RTOS to RGMP together with an unmodified
+ Linux to form a hybrid operating system. This makes your application
+ able to use both RTOS and GPOS features.
+
+ See http://rgmp.sourceforge.net/wiki/index.php/Main_Page for further
+ information about RGMP.
+
+arch/sh - SuperH and related Hitachi/Renesas microcontrollers
+
+ arch/sh/include and arch/sh/src/common
+ Common SuperH logic.
+
+ arch/sh/include/shs and arch/sh/src/sh1
+ Support for the SH-1 processor.
+
+arch/8051 - 8051/52 microcontrollers
+ 8051 Microcontroller. This port is not quite ready for prime time.
+
+arch/x86 - Intel x86 architectures
+ This directory holds related, 32- and 64-bit architectures from Intel.
+ At present, this includes the following subdirectories:
+
+ arch/x86/include and arch/x86/src/common
+ Common x86 logic.
+
+ arch/x86/include/i486 and arch/x86/src/i486
+ These directories hold definitions and logic appropriate for any
+ instantiation of the 32-bit i486 architecture.
+
+ arch/x86/include/qemu and arch/x86/src/qemu
+ This is the implementation of NuttX on the QEMU x86 simulation.
+
+arch/z16 - ZiLOG 16-bit processors
+ This directory holds related, 16-bit architectures from ZiLOG. At
+ present, this includes the following subdirectories:
+
+ arch/z16/include and arch/z16/src/common
+ Common microcontroller logic.
+
+ arch/z16/include/z16f and arch/z16/src/z16f
+ ZiLOG z16f Microcontroller.
+ STATUS: Released in nuttx-0.3.7. Fully functional other than issues
+ addressed in ${TOPDIR}/TODO.
+
+arch/z80 - ZiLOG 8-bit microcontrollers
+ This directory holds related, 8-bit architectures from ZiLOG. At
+ present, this includes the following subdirectories:
+
+ arch/z80/include and arch/z80/src/common
+ Common microcontroller logic.
+
+ arch/z80/include/z80 and arch/z80/src/z80
+ Classic ZiLOG z80 Microcontroller.
+ STATUS: Functional with no known defects. There are still several
+ OS features that have not yet been tested (e.g., networking).
+
+ arch/z80/include/z8 and arch/z80/src/z8
+ ZiLOG Z8Encore! Microcontroller
+
+ arch/z80/include/ez80 and arch/z80/src/ez80
+ ZiLOG ez80 Acclaim! Microcontroller
diff --git a/nuttx/arch/arm/Kconfig b/nuttx/arch/arm/Kconfig
new file mode 100644
index 000000000..40dcb1105
--- /dev/null
+++ b/nuttx/arch/arm/Kconfig
@@ -0,0 +1,206 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+if ARCH_ARM
+choice
+ prompt "ARM chip selection"
+ default ARCH_CHIP_STM32
+
+config ARCH_CHIP_C5471
+ bool "TMS320 C5471"
+ ---help---
+ TI TMS320 C5471, A180, or DA180 (ARM7TDMI)
+
+config ARCH_CHIP_CALYPSO
+ bool "Calypso"
+ ---help---
+ TI Calypso-based cell phones (ARM7TDMI)
+
+config ARCH_CHIP_DM320
+ bool "TMS320 DM320"
+ ---help---
+ TI DMS320 DM320 (ARM926EJS)
+
+config ARCH_CHIP_IMX
+ bool "Freescale iMX"
+ ---help---
+ Freescale iMX architectures (ARM920T)
+
+config ARCH_CHIP_KINETIS
+ bool "Freescale Kinetis"
+ ---help---
+ Freescale Kinetis Architectures (ARM Cortex-M4)
+
+config ARCH_CHIP_LM3S
+ bool "TI Stellaris"
+ ---help---
+ TI Stellaris LMS3 architecutres (ARM Cortex-M3)
+
+config ARCH_CHIP_LPC17XX
+ bool "NXP LPC17xx"
+ ---help---
+ NXP LPC17xx architectures (ARM Cortex-M3)
+
+config ARCH_CHIP_LPC214X
+ bool "NXP LPC214x"
+ ---help---
+ NXP LPC2145x architectures (ARM7TDMI)
+
+config ARCH_CHIP_LPC2378
+ bool "NXP LPC2378"
+ ---help---
+ NXP LPC2145x architectures (ARM7TDMI)
+
+config ARCH_CHIP_LPC31XX
+ bool "NXP LPC31XX"
+ ---help---
+ NPX LPC31XX architectures (ARM926EJS).
+
+config ARCH_CHIP_LPC43XX
+ bool "NXP LPC43XX"
+ ---help---
+ NPX LPC43XX architectures (ARM Cortex-M4).
+
+config ARCH_CHIP_SAM3U
+ bool "Atmel AT91SAM3U"
+ ---help---
+ Atmel AT91SAM3U architectures (ARM Cortex-M3)
+
+config ARCH_CHIP_STM32
+ bool "STMicro STM32"
+ ---help---
+ STMicro STM32 architectures (ARM Cortex-M3/4).
+
+config ARCH_CHIP_STR71X
+ bool "STMicro STR71x"
+ ---help---
+ STMicro STR71x architectures (ARM7TDMI).
+
+endchoice
+
+config ARCH_ARM7TDMI
+ bool
+ default y if ARCH_CHIP_C5471 || ARCH_CHIP_CALYPSO || ARCH_CHIP_LPC214X || ARCH_CHIP_LPC2378 || ARCH_CHIP_STR71X
+
+config ARCH_ARM926EJS
+ bool
+ default y if ARCH_CHIP_DM320 || ARCH_CHIP_LPC31XX
+
+config ARCH_ARM920T
+ bool
+ default y if ARCH_CHIP_IMX
+
+config ARCH_CORTEXM
+ bool
+ default y if ARCH_CHIP_KINETIS || ARCH_CHIP_LM3S || ARCH_CHIP_LPC17XX || ARCH_CHIP_LPC43XX || ARCH_CHIP_SAM3U || ARCH_CHIP_STM32
+
+config ARCH_FAMILY
+ string
+ default "arm" if ARCH_ARM7TDMI || ARCH_ARM926EJS || ARCH_ARM920T
+ default "armv7-m" if ARCH_CORTEXM
+
+config ARCH_CHIP
+ string
+ default "c5471" if ARCH_CHIP_C5471
+ default "calypso" if ARCH_CHIP_CALYPSO
+ default "dm320" if ARCH_CHIP_DM320
+ default "imx" if ARCH_CHIP_IMX
+ default "kinetis" if ARCH_CHIP_KINETIS
+ default "lm3s" if ARCH_CHIP_LM3S
+ default "lpc17x" if ARCH_CHIP_LPC17XX
+ default "lpc214x" if ARCH_CHIP_LPC214X
+ default "lpc2378" if ARCH_CHIP_LPC2378
+ default "lpc31xx" if ARCH_CHIP_LPC31XX
+ default "lpc43xx" if ARCH_CHIP_LPC43XX
+ default "sam3u" if ARCH_CHIP_SAM3U
+ default "stm32" if ARCH_CHIP_STM32
+ default "str71x" if ARCH_CHIP_STR71X
+
+config ARCH_STACKDUMP
+ bool "Dump stack on assertions"
+ default n
+ ---help---
+ Enable to do stack dumps after assertions
+
+config ARCH_LEDS
+ bool "Use board LEDs to show state"
+ default y
+ ---help---
+ Use LEDs to show state. Unique to boards that have LEDs
+
+config ARCH_INTERRUPTSTACK
+ bool "Use interrupt stack"
+ default y
+ ---help---
+ This architecture supports an interrupt stack. If defined, this symbol
+ is the size of the interrupt stack in bytes. If not defined, the user
+ task stacks will be used during interrupt handling.
+
+config ARCH_IRQPRIO
+ bool "Interrupt priority"
+ default y if ARCH_CORTEXM
+ ---help---
+ Select if your board supports interrupt prioritization.
+
+config ARCH_LOOPSPERMSEC
+ int "Delay loops per millisecond"
+ default 5000
+ ---help---
+ Delay loops nust be calibrated for correct operation.
+
+config ARCH_CALIBRATION
+ bool "Calibrate delay loop"
+ default n
+ ---help---
+ Enables some built in instrumentation that causes a 100 second delay
+ during boot-up. This 100 second delay serves no purpose other than it
+ allows you to calibratre ARCH_LOOPSPERMSEC. You simply use a stop
+ watch to measure the 100 second delay then adjust ARCH_LOOPSPERMSEC until
+ the delay actually is 100 seconds.
+
+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
+if ARCH_CHIP_IMX
+source arch/arm/src/imx/Kconfig
+endif
+if ARCH_CHIP_KINETIS
+source arch/arm/src/kinetis/Kconfig
+endif
+if ARCH_CHIP_LM3S
+source arch/arm/src/lm3s/Kconfig
+endif
+if ARCH_CHIP_LPC17XX
+source arch/arm/src/lpc17xx/Kconfig
+endif
+if ARCH_CHIP_LPC214X
+source arch/arm/src/lpc214x/Kconfig
+endif
+if ARCH_CHIP_LPC2378
+source arch/arm/src/lpc2378/Kconfig
+endif
+if ARCH_CHIP_LPC31XX
+source arch/arm/src/lpc31xx/Kconfig
+endif
+if ARCH_CHIP_LPC43XX
+source arch/arm/src/lpc43xx/Kconfig
+endif
+if ARCH_CHIP_SAM3U
+source arch/arm/src/sam3u/Kconfig
+endif
+if ARCH_CHIP_STM32
+source arch/arm/src/stm32/Kconfig
+endif
+if ARCH_CHIP_STR71X
+source arch/arm/src/str71x/Kconfig
+endif
+
+endif
diff --git a/nuttx/arch/arm/include/arch.h b/nuttx/arch/arm/include/arch.h
new file mode 100644
index 000000000..dd750ad77
--- /dev/null
+++ b/nuttx/arch/arm/include/arch.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+ * arch/arm/include/arch.h
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directed but, rather,
+ * only indirectly through nuttx/arch.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_ARCH_H
+#define __ARCH_ARM_INCLUDE_ARCH_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#ifndef __ASSEMBLY__
+# include <stdint.h>
+#endif
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_PIC
+
+/* This identifies the register the is used by the processor as the PIC base
+ * register. It is usually r9 or r10
+ */
+
+#define PIC_REG r10
+#define PIC_REG_STRING "r10"
+
+/* Macros to get and set the PIC base register. picbase is assumed to be
+ * of type (void*) and that it will fit into a uint32_t. These must be
+ * inline so that they will be compatible with the ABIs rules for
+ * preserving the PIC register
+ */
+
+#define up_getpicbase(ppicbase) \
+do { \
+ uint32_t picbase; \
+ __asm__ \
+ ( \
+ "\tmov %0, " PIC_REG_STRING "\n\t" \
+ : "=r"(picbase) \
+ ); \
+ *ppicbase = (FAR void*)picbase; \
+} while (0)
+
+#define up_setpicbase(picbase) \
+do { \
+ uint32_t _picbase = (uint32_t)picbase; \
+ __asm__ \
+ ( \
+ "\tmov " PIC_REG_STRING ", %0\n\t" \
+ : : "r"(_picbase) : PIC_REG_STRING \
+ ); \
+} while (0)
+
+#endif
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_ARCH_H */
diff --git a/nuttx/arch/arm/include/arm/irq.h b/nuttx/arch/arm/include/arm/irq.h
new file mode 100644
index 000000000..6b4f05539
--- /dev/null
+++ b/nuttx/arch/arm/include/arm/irq.h
@@ -0,0 +1,231 @@
+/****************************************************************************
+ * arch/arm/include/arm/irq.h
+ *
+ * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directed but, rather, only indirectly
+ * through nuttx/irq.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_ARM_IRQ_H
+#define __ARCH_ARM_INCLUDE_ARM_IRQ_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/irq.h>
+#ifndef __ASSEMBLY__
+# include <stdint.h>
+#endif
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* IRQ Stack Frame Format:
+ *
+ * Context is always saved/restored in the same way:
+ *
+ * (1) stmia rx, {r0-r14}
+ * (2) then the PC and CPSR
+ *
+ * This results in the following set of indices that
+ * can be used to access individual registers in the
+ * xcp.regs array:
+ */
+
+#define REG_R0 (0)
+#define REG_R1 (1)
+#define REG_R2 (2)
+#define REG_R3 (3)
+#define REG_R4 (4)
+#define REG_R5 (5)
+#define REG_R6 (6)
+#define REG_R7 (7)
+#define REG_R8 (8)
+#define REG_R9 (9)
+#define REG_R10 (10)
+#define REG_R11 (11)
+#define REG_R12 (12)
+#define REG_R13 (13)
+#define REG_R14 (14)
+#define REG_R15 (15)
+#define REG_CPSR (16)
+
+#define XCPTCONTEXT_REGS (17)
+#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS)
+
+#define REG_A1 REG_R0
+#define REG_A2 REG_R1
+#define REG_A3 REG_R2
+#define REG_A4 REG_R3
+#define REG_V1 REG_R4
+#define REG_V2 REG_R5
+#define REG_V3 REG_R6
+#define REG_V4 REG_R7
+#define REG_V5 REG_R8
+#define REG_V6 REG_R9
+#define REG_V7 REG_R10
+#define REG_SB REG_R9
+#define REG_SL REG_R10
+#define REG_FP REG_R11
+#define REG_IP REG_R12
+#define REG_SP REG_R13
+#define REG_LR REG_R14
+#define REG_PC REG_R15
+
+/* The PIC register is usually R10. It can be R9 is stack checking is enabled
+ * or if the user changes it with -mpic-register on the GCC command line.
+ */
+
+#define REG_PIC REG_R10
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* This struct defines the way the registers are stored. We
+ * need to save:
+ *
+ * 1 CPSR
+ * 7 Static registers, v1-v7 (aka r4-r10)
+ * 1 Frame pointer, fp (aka r11)
+ * 1 Stack pointer, sp (aka r13)
+ * 1 Return address, lr (aka r14)
+ * ---
+ * 11 (XCPTCONTEXT_USER_REG)
+ *
+ * On interrupts, we also need to save:
+ * 4 Volatile registers, a1-a4 (aka r0-r3)
+ * 1 Scratch Register, ip (aka r12)
+ *---
+ * 5 (XCPTCONTEXT_IRQ_REGS)
+ *
+ * For a total of 17 (XCPTCONTEXT_REGS)
+ */
+
+#ifndef __ASSEMBLY__
+struct xcptcontext
+{
+ /* The following function pointer is non-zero if there
+ * are pending signals to be processed.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ void *sigdeliver; /* Actual type is sig_deliver_t */
+
+ /* These are saved copies of LR and CPSR used during
+ * signal processing.
+ */
+
+ uint32_t saved_pc;
+ uint32_t saved_cpsr;
+#endif
+
+ /* Register save area */
+
+ uint32_t regs[XCPTCONTEXT_REGS];
+
+ /* Extra fault address register saved for common paging logic. In the
+ * case of the prefetch abort, this value is the same as regs[REG_R15];
+ * For the case of the data abort, this value is the value of the fault
+ * address register (FAR) at the time of data abort exception.
+ */
+
+#ifdef CONFIG_PAGING
+ uintptr_t far;
+#endif
+};
+#endif
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/* Save the current interrupt enable state & disable IRQs */
+
+static inline irqstate_t irqsave(void)
+{
+ unsigned int flags;
+ unsigned int temp;
+ __asm__ __volatile__
+ (
+ "\tmrs %0, cpsr\n"
+ "\torr %1, %0, #128\n"
+ "\tmsr cpsr_c, %1"
+ : "=r" (flags), "=r" (temp)
+ :
+ : "memory");
+ return flags;
+}
+
+/* Restore saved IRQ & FIQ state */
+
+static inline void irqrestore(irqstate_t flags)
+{
+ __asm__ __volatile__
+ (
+ "msr cpsr_c, %0"
+ :
+ : "r" (flags)
+ : "memory");
+}
+#endif /* __ASSEMBLY__ */
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_ARM_IRQ_H */
+
diff --git a/nuttx/arch/arm/include/arm/syscall.h b/nuttx/arch/arm/include/arm/syscall.h
new file mode 100644
index 000000000..e06de1a3c
--- /dev/null
+++ b/nuttx/arch/arm/include/arm/syscall.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+ * arch/arm/include/arm/syscall.h
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directed but, rather, only indirectly
+ * through include/syscall.h or include/sys/sycall.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_ARM_SYSCALL_H
+#define __ARCH_ARM_INCLUDE_ARM_SYSCALL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifndef __ASSEMBLY__
+# include <stdint.h>
+#endif
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+#define SYS_syscall 0x900001
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/* SWI with SYS_ call number and no parameters */
+
+static inline uintptr_t sys_call0(unsigned int nbr)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+
+ __asm__ __volatile__
+ (
+ "swi %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SWI with SYS_ call number and one parameter */
+
+static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "swi %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SWI with SYS_ call number and two parameters */
+
+static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "swi %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SWI with SYS_ call number and three parameters */
+
+static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2, uintptr_t parm3)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg3 __asm__("r3") = (long)(parm3);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "swi %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), "r"(reg3)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SWI with SYS_ call number and four parameters */
+
+static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2, uintptr_t parm3,
+ uintptr_t parm4)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg4 __asm__("r4") = (long)(parm4);
+ register long reg3 __asm__("r3") = (long)(parm3);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "swi %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2),
+ "r"(reg3), "r"(reg4)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SWI with SYS_ call number and five parameters */
+
+static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2, uintptr_t parm3,
+ uintptr_t parm4, uintptr_t parm5)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg5 __asm__("r5") = (long)(parm5);
+ register long reg4 __asm__("r4") = (long)(parm4);
+ register long reg3 __asm__("r3") = (long)(parm3);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "swi %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2),
+ "r"(reg3), "r"(reg4), "r"(reg5)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SWI with SYS_ call number and six parameters */
+
+static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2, uintptr_t parm3,
+ uintptr_t parm4, uintptr_t parm5,
+ uintptr_t parm6)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg6 __asm__("r6") = (long)(parm6);
+ register long reg5 __asm__("r5") = (long)(parm5);
+ register long reg4 __asm__("r4") = (long)(parm4);
+ register long reg3 __asm__("r3") = (long)(parm3);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "swi %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2),
+ "r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_INCLUDE_ARM_SYSCALL_H */
+
diff --git a/nuttx/arch/arm/include/armv7-m/irq.h b/nuttx/arch/arm/include/armv7-m/irq.h
new file mode 100644
index 000000000..6cef85c02
--- /dev/null
+++ b/nuttx/arch/arm/include/armv7-m/irq.h
@@ -0,0 +1,306 @@
+/****************************************************************************
+ * arch/arm/include/armv7-m/irq.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directed but, rather, only indirectly
+ * through nuttx/irq.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_H
+#define __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/irq.h>
+#ifndef __ASSEMBLY__
+# include <stdint.h>
+#endif
+
+/* Included implementation-dependent register save structure layouts */
+
+#ifdef CONFIG_ARMV7M_CMNVECTOR
+# include <arch/armv7-m/irq_cmnvector.h>
+#else
+# include <arch/armv7-m/irq_lazyfpu.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Alternate register names */
+
+#define REG_A1 REG_R0
+#define REG_A2 REG_R1
+#define REG_A3 REG_R2
+#define REG_A4 REG_R3
+#define REG_V1 REG_R4
+#define REG_V2 REG_R5
+#define REG_V3 REG_R6
+#define REG_V4 REG_R7
+#define REG_V5 REG_R8
+#define REG_V6 REG_R9
+#define REG_V7 REG_R10
+#define REG_SB REG_R9
+#define REG_SL REG_R10
+#define REG_FP REG_R11
+#define REG_IP REG_R12
+#define REG_SP REG_R13
+#define REG_LR REG_R14
+#define REG_PC REG_R15
+
+/* The PIC register is usually R10. It can be R9 is stack checking is enabled
+ * or if the user changes it with -mpic-register on the GCC command line.
+ */
+
+#define REG_PIC REG_R10
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* The following structure is included in the TCB and defines the complete
+ * state of the thread.
+ */
+
+#ifndef __ASSEMBLY__
+struct xcptcontext
+{
+ /* The following function pointer is non-zero if there
+ * are pending signals to be processed.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ void *sigdeliver; /* Actual type is sig_deliver_t */
+
+ /* These are saved copies of LR, PRIMASK, and xPSR used during
+ * signal processing.
+ */
+
+ uint32_t saved_pc;
+ uint32_t saved_primask;
+ uint32_t saved_xpsr;
+#endif
+
+ /* Register save area */
+
+ uint32_t regs[XCPTCONTEXT_REGS];
+};
+#endif
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/* Disable IRQs */
+
+static inline void irqdisable(void)
+{
+ __asm__ __volatile__ ("\tcpsid i\n");
+}
+
+/* Save the current primask state & disable IRQs */
+
+static inline irqstate_t irqsave(void)
+{
+ unsigned short primask;
+
+ /* Return the current value of primask register and set
+ * bit 0 of the primask register to disable interrupts
+ */
+
+ __asm__ __volatile__
+ (
+ "\tmrs %0, primask\n"
+ "\tcpsid i\n"
+ : "=r" (primask)
+ :
+ : "memory");
+ return primask;
+}
+
+/* Enable IRQs */
+
+static inline void irqenable(void)
+{
+ __asm__ __volatile__ ("\tcpsie i\n");
+}
+
+/* Restore saved primask state */
+
+static inline void irqrestore(irqstate_t primask)
+{
+ /* If bit 0 of the primask is 0, then we need to restore
+ * interupts.
+ */
+
+ __asm__ __volatile__
+ (
+ "\ttst %0, #1\n"
+ "\tbne 1f\n"
+ "\tcpsie i\n"
+ "1:\n"
+ :
+ : "r" (primask)
+ : "memory");
+}
+
+/* Get/set the primask register */
+
+static inline uint8_t getprimask(void)
+{
+ uint32_t primask;
+ __asm__ __volatile__
+ (
+ "\tmrs %0, primask\n"
+ : "=r" (primask)
+ :
+ : "memory");
+ return (uint8_t)primask;
+}
+
+static inline void setprimask(uint32_t primask)
+{
+ __asm__ __volatile__
+ (
+ "\tmsr primask, %0\n"
+ :
+ : "r" (primask)
+ : "memory");
+}
+
+/* Get/set the basepri register */
+
+static inline uint8_t getbasepri(void)
+{
+ uint32_t basepri;
+ __asm__ __volatile__
+ (
+ "\tmrs %0, basepri\n"
+ : "=r" (basepri)
+ :
+ : "memory");
+ return (uint8_t)basepri;
+}
+
+static inline void setbasepri(uint32_t basepri)
+{
+ __asm__ __volatile__
+ (
+ "\tmsr basepri, %0\n"
+ :
+ : "r" (basepri)
+ : "memory");
+}
+
+/* Get/set IPSR */
+
+static inline uint32_t getipsr(void)
+{
+ uint32_t ipsr;
+ __asm__ __volatile__
+ (
+ "\tmrs %0, ipsr\n"
+ : "=r" (ipsr)
+ :
+ : "memory");
+ return ipsr;
+}
+
+static inline void setipsr(uint32_t ipsr)
+{
+ __asm__ __volatile__
+ (
+ "\tmsr ipsr, %0\n"
+ :
+ : "r" (ipsr)
+ : "memory");
+}
+
+/* Get/set CONTROL */
+
+static inline uint32_t getcontrol(void)
+{
+ uint32_t control;
+ __asm__ __volatile__
+ (
+ "\tmrs %0, control\n"
+ : "=r" (control)
+ :
+ : "memory");
+ return control;
+}
+
+static inline void setcontrol(uint32_t control)
+{
+ __asm__ __volatile__
+ (
+ "\tmsr control, %0\n"
+ :
+ : "r" (control)
+ : "memory");
+}
+
+#endif /* __ASSEMBLY__ */
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_H */
+
diff --git a/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h b/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h
new file mode 100644
index 000000000..e646731eb
--- /dev/null
+++ b/nuttx/arch/arm/include/armv7-m/irq_cmnvector.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+ * arch/arm/include/armv7-m/irq_cmnvector.h
+ *
+ * Copyright (C) 2012 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_INCLUDE_ARMV7_M_IRQ_CMNVECTOR_H
+#define __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_CMNVECTOR_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* IRQ Stack Frame Format: */
+
+/* The following additional registers are stored by the interrupt handling
+ * logic.
+ */
+
+#define REG_R13 (0) /* R13 = SP at time of interrupt */
+#define REG_PRIMASK (1) /* PRIMASK */
+#define REG_R4 (2) /* R4 */
+#define REG_R5 (3) /* R5 */
+#define REG_R6 (4) /* R6 */
+#define REG_R7 (5) /* R7 */
+#define REG_R8 (6) /* R8 */
+#define REG_R9 (7) /* R9 */
+#define REG_R10 (8) /* R10 */
+#define REG_R11 (9) /* R11 */
+#define REG_EXC_RETURN (10) /* EXC_RETURN */
+#define SW_INT_REGS (11)
+
+#ifdef CONFIG_ARCH_FPU
+
+/* If the MCU supports a floating point unit, then it will be necessary
+ * to save the state of the non-volatile registers before calling code
+ * that may save and overwrite them.
+ */
+
+# define REG_S16 (SW_INT_REGS+0) /* S16 */
+# define REG_S17 (SW_INT_REGS+1) /* S17 */
+# define REG_S18 (SW_INT_REGS+2) /* S18 */
+# define REG_S19 (SW_INT_REGS+3) /* S19 */
+# define REG_S20 (SW_INT_REGS+4) /* S20 */
+# define REG_S21 (SW_INT_REGS+5) /* S21 */
+# define REG_S22 (SW_INT_REGS+6) /* S22 */
+# define REG_S23 (SW_INT_REGS+7) /* S23 */
+# define REG_S24 (SW_INT_REGS+8) /* S24 */
+# define REG_S25 (SW_INT_REGS+9) /* S25 */
+# define REG_S26 (SW_INT_REGS+10) /* S26 */
+# define REG_S27 (SW_INT_REGS+11) /* S27 */
+# define REG_S28 (SW_INT_REGS+12) /* S28 */
+# define REG_S29 (SW_INT_REGS+13) /* S29 */
+# define REG_S30 (SW_INT_REGS+14) /* S30 */
+# define REG_S31 (SW_INT_REGS+15) /* S31 */
+# define SW_FPU_REGS (16)
+#else
+# define SW_FPU_REGS (0)
+#endif
+
+/* The total number of registers saved by software */
+
+#define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS)
+#define SW_XCPT_SIZE (4 * SW_XCPT_REGS)
+
+/* On entry into an IRQ, the hardware automatically saves the following
+ * registers on the stack in this (address) order:
+ */
+
+#define REG_R0 (SW_XCPT_REGS+0) /* R0 */
+#define REG_R1 (SW_XCPT_REGS+1) /* R1 */
+#define REG_R2 (SW_XCPT_REGS+2) /* R2 */
+#define REG_R3 (SW_XCPT_REGS+3) /* R3 */
+#define REG_R12 (SW_XCPT_REGS+4) /* R12 */
+#define REG_R14 (SW_XCPT_REGS+5) /* R14 = LR */
+#define REG_R15 (SW_XCPT_REGS+6) /* R15 = PC */
+#define REG_XPSR (SW_XCPT_REGS+7) /* xPSR */
+#define HW_INT_REGS (8)
+
+#ifdef CONFIG_ARCH_FPU
+
+/* If the FPU is enabled, the hardware also saves the volatile FP registers.
+ */
+
+# define REG_S0 (SW_XCPT_REGS+8) /* S0 */
+# define REG_S1 (SW_XCPT_REGS+9) /* S1 */
+# define REG_S2 (SW_XCPT_REGS+10) /* S2 */
+# define REG_S3 (SW_XCPT_REGS+11) /* S3 */
+# define REG_S4 (SW_XCPT_REGS+12) /* S4 */
+# define REG_S5 (SW_XCPT_REGS+13) /* S5 */
+# define REG_S6 (SW_XCPT_REGS+14) /* S6 */
+# define REG_S7 (SW_XCPT_REGS+15) /* S7 */
+# define REG_S8 (SW_XCPT_REGS+16) /* S8 */
+# define REG_S9 (SW_XCPT_REGS+17) /* S9 */
+# define REG_S10 (SW_XCPT_REGS+18) /* S10 */
+# define REG_S11 (SW_XCPT_REGS+19) /* S11 */
+# define REG_S12 (SW_XCPT_REGS+20) /* S12 */
+# define REG_S13 (SW_XCPT_REGS+21) /* S13 */
+# define REG_S14 (SW_XCPT_REGS+22) /* S14 */
+# define REG_S15 (SW_XCPT_REGS+23) /* S15 */
+# define REG_FPSCR (SW_XCPT_REGS+24) /* FPSCR */
+# define REG_FPReserved (SW_XCPT_REGS+25) /* Reserved */
+# define HW_FPU_REGS (18)
+#else
+# define HW_FPU_REGS (0)
+#endif
+
+#define HW_XCPT_REGS (HW_INT_REGS + HW_FPU_REGS)
+#define HW_XCPT_SIZE (4 * HW_XCPT_REGS)
+
+#define XCPTCONTEXT_REGS (HW_XCPT_REGS + SW_XCPT_REGS)
+#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#endif /* __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_CMNVECTOR_H */
+
diff --git a/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h b/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h
new file mode 100644
index 000000000..2c3600b7f
--- /dev/null
+++ b/nuttx/arch/arm/include/armv7-m/irq_lazyfpu.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+ * arch/arm/include/armv7-m/irq.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_INCLUDE_ARMV7_M_IRQ_LAZYFPU_H
+#define __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_LAZYFPU_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* IRQ Stack Frame Format: */
+
+/* The following additional registers are stored by the interrupt handling
+ * logic.
+ */
+
+#define REG_R13 (0) /* R13 = SP at time of interrupt */
+#define REG_PRIMASK (1) /* PRIMASK */
+#define REG_R4 (2) /* R4 */
+#define REG_R5 (3) /* R5 */
+#define REG_R6 (4) /* R6 */
+#define REG_R7 (5) /* R7 */
+#define REG_R8 (6) /* R8 */
+#define REG_R9 (7) /* R9 */
+#define REG_R10 (8) /* R10 */
+#define REG_R11 (9) /* R11 */
+
+#ifdef CONFIG_NUTTX_KERNEL
+# define REG_EXC_RETURN (10) /* EXC_RETURN */
+# define SW_INT_REGS (11)
+#else
+# define SW_INT_REGS (10)
+#endif
+
+/* If the MCU supports a floating point unit, then it will be necessary
+ * to save the state of the FPU status register and data registers on
+ * each context switch. These registers are not saved during interrupt
+ * level processing, however. So, as a consequence, floating point
+ * operations may NOT be performed in interrupt handlers.
+ *
+ * The FPU provides an extension register file containing 32 single-
+ * precision registers. These can be viewed as:
+ *
+ * - Sixteen 64-bit doubleword registers, D0-D15
+ * - Thirty-two 32-bit single-word registers, S0-S31
+ * S<2n> maps to the least significant half of D<n>
+ * S<2n+1> maps to the most significant half of D<n>.
+ */
+
+#ifdef CONFIG_ARCH_FPU
+# define REG_D0 (SW_INT_REGS+0) /* D0 */
+# define REG_S0 (SW_INT_REGS+0) /* S0 */
+# define REG_S1 (SW_INT_REGS+1) /* S1 */
+# define REG_D1 (SW_INT_REGS+2) /* D1 */
+# define REG_S2 (SW_INT_REGS+2) /* S2 */
+# define REG_S3 (SW_INT_REGS+3) /* S3 */
+# define REG_D2 (SW_INT_REGS+4) /* D2 */
+# define REG_S4 (SW_INT_REGS+4) /* S4 */
+# define REG_S5 (SW_INT_REGS+5) /* S5 */
+# define REG_D3 (SW_INT_REGS+6) /* D3 */
+# define REG_S6 (SW_INT_REGS+6) /* S6 */
+# define REG_S7 (SW_INT_REGS+7) /* S7 */
+# define REG_D4 (SW_INT_REGS+8) /* D4 */
+# define REG_S8 (SW_INT_REGS+8) /* S8 */
+# define REG_S9 (SW_INT_REGS+9) /* S9 */
+# define REG_D5 (SW_INT_REGS+10) /* D5 */
+# define REG_S10 (SW_INT_REGS+10) /* S10 */
+# define REG_S11 (SW_INT_REGS+11) /* S11 */
+# define REG_D6 (SW_INT_REGS+12) /* D6 */
+# define REG_S12 (SW_INT_REGS+12) /* S12 */
+# define REG_S13 (SW_INT_REGS+13) /* S13 */
+# define REG_D7 (SW_INT_REGS+14) /* D7 */
+# define REG_S14 (SW_INT_REGS+14) /* S14 */
+# define REG_S15 (SW_INT_REGS+15) /* S15 */
+# define REG_D8 (SW_INT_REGS+16) /* D8 */
+# define REG_S16 (SW_INT_REGS+16) /* S16 */
+# define REG_S17 (SW_INT_REGS+17) /* S17 */
+# define REG_D9 (SW_INT_REGS+18) /* D9 */
+# define REG_S18 (SW_INT_REGS+18) /* S18 */
+# define REG_S19 (SW_INT_REGS+19) /* S19 */
+# define REG_D10 (SW_INT_REGS+20) /* D10 */
+# define REG_S20 (SW_INT_REGS+20) /* S20 */
+# define REG_S21 (SW_INT_REGS+21) /* S21 */
+# define REG_D11 (SW_INT_REGS+22) /* D11 */
+# define REG_S22 (SW_INT_REGS+22) /* S22 */
+# define REG_S23 (SW_INT_REGS+23) /* S23 */
+# define REG_D12 (SW_INT_REGS+24) /* D12 */
+# define REG_S24 (SW_INT_REGS+24) /* S24 */
+# define REG_S25 (SW_INT_REGS+25) /* S25 */
+# define REG_D13 (SW_INT_REGS+26) /* D13 */
+# define REG_S26 (SW_INT_REGS+26) /* S26 */
+# define REG_S27 (SW_INT_REGS+27) /* S27 */
+# define REG_D14 (SW_INT_REGS+28) /* D14 */
+# define REG_S28 (SW_INT_REGS+28) /* S28 */
+# define REG_S29 (SW_INT_REGS+29) /* S29 */
+# define REG_D15 (SW_INT_REGS+30) /* D15 */
+# define REG_S30 (SW_INT_REGS+30) /* S30 */
+# define REG_S31 (SW_INT_REGS+31) /* S31 */
+# define REG_FPSCR (SW_INT_REGS+32) /* Floating point status and control */
+# define SW_FPU_REGS (33)
+#else
+# define SW_FPU_REGS (0)
+#endif
+
+/* The total number of registers saved by software */
+
+#define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS)
+#define SW_XCPT_SIZE (4 * SW_XCPT_REGS)
+
+/* On entry into an IRQ, the hardware automatically saves the following
+ * registers on the stack in this (address) order:
+ */
+
+#define REG_R0 (SW_XCPT_REGS+0) /* R0 */
+#define REG_R1 (SW_XCPT_REGS+1) /* R1 */
+#define REG_R2 (SW_XCPT_REGS+2) /* R2 */
+#define REG_R3 (SW_XCPT_REGS+3) /* R3 */
+#define REG_R12 (SW_XCPT_REGS+4) /* R12 */
+#define REG_R14 (SW_XCPT_REGS+5) /* R14 = LR */
+#define REG_R15 (SW_XCPT_REGS+6) /* R15 = PC */
+#define REG_XPSR (SW_XCPT_REGS+7) /* xPSR */
+
+#define HW_XCPT_REGS (8)
+#define HW_XCPT_SIZE (4 * HW_XCPT_REGS)
+
+#define XCPTCONTEXT_REGS (HW_XCPT_REGS + SW_XCPT_REGS)
+#define XCPTCONTEXT_SIZE (HW_XCPT_SIZE + SW_XCPT_SIZE)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#endif /* __ARCH_ARM_INCLUDE_ARMV7_M_IRQ_LAZYFPU_H */
+
diff --git a/nuttx/arch/arm/include/armv7-m/syscall.h b/nuttx/arch/arm/include/armv7-m/syscall.h
new file mode 100644
index 000000000..4c7b84302
--- /dev/null
+++ b/nuttx/arch/arm/include/armv7-m/syscall.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+ * arch/arm/include/armv7-m/syscall.h
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directed but, rather, only indirectly
+ * through include/syscall.h or include/sys/sycall.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_ARMV7_M_SYSCALL_H
+#define __ARCH_ARM_INCLUDE_ARMV7_M_SYSCALL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifndef __ASSEMBLY__
+# include <stdint.h>
+#endif
+
+/****************************************************************************
+ * Pro-processor Definitions
+ ****************************************************************************/
+
+#define SYS_syscall 0x00
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/* SVC call with SYS_ call number and no parameters */
+
+static inline uintptr_t sys_call0(unsigned int nbr)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+
+ __asm__ __volatile__
+ (
+ "svc %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SVC call with SYS_ call number and one parameter */
+
+static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "svc %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SVC call with SYS_ call number and two parameters */
+
+static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "svc %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SVC call with SYS_ call number and three parameters */
+
+static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2, uintptr_t parm3)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg3 __asm__("r3") = (long)(parm3);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "svc %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), "r"(reg3)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SVC call with SYS_ call number and four parameters */
+
+static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2, uintptr_t parm3,
+ uintptr_t parm4)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg4 __asm__("r4") = (long)(parm4);
+ register long reg3 __asm__("r3") = (long)(parm3);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "svc %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2),
+ "r"(reg3), "r"(reg4)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SVC call with SYS_ call number and five parameters */
+
+static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2, uintptr_t parm3,
+ uintptr_t parm4, uintptr_t parm5)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg5 __asm__("r5") = (long)(parm5);
+ register long reg4 __asm__("r4") = (long)(parm4);
+ register long reg3 __asm__("r3") = (long)(parm3);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "svc %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2),
+ "r"(reg3), "r"(reg4), "r"(reg5)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/* SVC call with SYS_ call number and six parameters */
+
+static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
+ uintptr_t parm2, uintptr_t parm3,
+ uintptr_t parm4, uintptr_t parm5,
+ uintptr_t parm6)
+{
+ register long reg0 __asm__("r0") = (long)(nbr);
+ register long reg6 __asm__("r6") = (long)(parm6);
+ register long reg5 __asm__("r5") = (long)(parm5);
+ register long reg4 __asm__("r4") = (long)(parm4);
+ register long reg3 __asm__("r3") = (long)(parm3);
+ register long reg2 __asm__("r2") = (long)(parm2);
+ register long reg1 __asm__("r1") = (long)(parm1);
+
+ __asm__ __volatile__
+ (
+ "svc %1"
+ : "=r"(reg0)
+ : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2),
+ "r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6)
+ : "memory"
+ );
+
+ return reg0;
+}
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_INCLUDE_ARMV7_M_SYSCALL_H */
+
diff --git a/nuttx/arch/arm/include/irq.h b/nuttx/arch/arm/include/irq.h
new file mode 100644
index 000000000..71493a9fe
--- /dev/null
+++ b/nuttx/arch/arm/include/irq.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * arch/arm/include/irq.h
+ *
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directed but, rather, only indirectly
+ * through nuttx/irq.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_IRQ_H
+#define __ARCH_ARM_INCLUDE_IRQ_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/* Include NuttX-specific IRQ definitions */
+
+#include <nuttx/irq.h>
+
+/* Include chip-specific IRQ definitions (including IRQ numbers) */
+
+#include <arch/chip/irq.h>
+
+/* Include ARM architecture-specific IRQ definitions (including register
+ * save structure and irqsave()/irqrestore() macros)
+ */
+
+#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4)
+# include <arch/armv7-m/irq.h>
+#else
+# include <arch/arm/irq.h>
+#endif
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_IRQ_H */
+
diff --git a/nuttx/arch/arm/include/limits.h b/nuttx/arch/arm/include/limits.h
new file mode 100644
index 000000000..a218d53bf
--- /dev/null
+++ b/nuttx/arch/arm/include/limits.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+ * arch/arm/include/limits.h
+ *
+ * Copyright (C) 2007-2009, 2012 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_INCLUDE_LIMITS_H
+#define __ARCH_ARM_INCLUDE_LIMITS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define CHAR_BIT 8
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+#define UCHAR_MAX 0xff
+
+/* These could be different on machines where char is unsigned */
+
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+#define SHRT_MIN 0x8000
+#define SHRT_MAX 0x7fff
+#define USHRT_MAX 0xffff
+
+#define INT_MIN 0x80000000
+#define INT_MAX 0x7fffffff
+#define UINT_MAX 0xffffffff
+
+/* These change on 32-bit and 64-bit platforms */
+
+#define LONG_MAX 0x80000000
+#define LONG_MIN 0x7fffffff
+#define ULONG_MAX 0xffffffff
+
+#define LLONG_MAX 0x8000000000000000
+#define LLONG_MIN 0x7fffffffffffffff
+#define ULLONG_MAX 0xffffffffffffffff
+
+/* A pointer is 4 bytes */
+
+#define PTR_MIN 0x80000000
+#define PTR_MAX 0x7fffffff
+#define UPTR_MAX 0xffffffff
+
+#endif /* __ARCH_ARM_INCLUDE_LIMITS_H */
diff --git a/nuttx/arch/arm/include/math.h b/nuttx/arch/arm/include/math.h
new file mode 100644
index 000000000..ef0869243
--- /dev/null
+++ b/nuttx/arch/arm/include/math.h
@@ -0,0 +1,608 @@
+#ifndef _MATH_H_
+
+#define _MATH_H_
+
+//#include <sys/reent.h>
+#include <machine/ieeefp.h>
+#include "_ansi.h"
+
+//#define _PARAMS(_x) _x
+
+_BEGIN_STD_C
+
+#if 0
+/* __dmath, __fmath, and __ldmath are only here for backwards compatibility
+ * in case any code used them. They are no longer used by Newlib, itself,
+ * other than legacy. */
+union __dmath
+{
+ double d;
+ __ULong i[2];
+};
+
+union __fmath
+{
+ float f;
+ __ULong i[1];
+};
+
+#if defined(_HAVE_LONG_DOUBLE)
+union __ldmath
+{
+ long double ld;
+ __ULong i[4];
+};
+#endif
+#endif
+
+/* Natural log of 2 */
+#define _M_LN2 0.693147180559945309417
+
+#if defined(__GNUC__) && \
+ ( (__GNUC__ >= 4) || \
+ ( (__GNUC__ >= 3) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 3) ) )
+
+ /* gcc >= 3.3 implicitly defines builtins for HUGE_VALx values. */
+
+# ifndef HUGE_VAL
+# define HUGE_VAL (__builtin_huge_val())
+# endif
+
+# ifndef HUGE_VALF
+# define HUGE_VALF (__builtin_huge_valf())
+# endif
+
+# ifndef HUGE_VALL
+# define HUGE_VALL (__builtin_huge_vall())
+# endif
+
+# ifndef INFINITY
+# define INFINITY (__builtin_inff())
+# endif
+
+# ifndef NAN
+# define NAN (__builtin_nanf(""))
+# endif
+
+#else /* !gcc >= 3.3 */
+
+ /* No builtins. Use fixed defines instead. (All 3 HUGE plus the INFINITY
+ * and NAN macros are required to be constant expressions. Using a variable--
+ * even a static const--does not meet this requirement, as it cannot be
+ * evaluated at translation time.)
+ * The infinities are done using numbers that are far in excess of
+ * something that would be expected to be encountered in a floating-point
+ * implementation. (A more certain way uses values from float.h, but that is
+ * avoided because system includes are not supposed to include each other.)
+ * This method might produce warnings from some compilers. (It does in
+ * newer GCCs, but not for ones that would hit this #else.) If this happens,
+ * please report details to the Newlib mailing list. */
+
+ #ifndef HUGE_VAL
+ #define HUGE_VAL (1.0e999999999)
+ #endif
+
+ #ifndef HUGE_VALF
+ #define HUGE_VALF (1.0e999999999F)
+ #endif
+
+ #if !defined(HUGE_VALL) && defined(_HAVE_LONG_DOUBLE)
+ #define HUGE_VALL (1.0e999999999L)
+ #endif
+
+ #if !defined(INFINITY)
+ #define INFINITY (HUGE_VALF)
+ #endif
+
+ #if !defined(NAN)
+ #if defined(__GNUC__) && defined(__cplusplus)
+ /* Exception: older g++ versions warn about the divide by 0 used in the
+ * normal case (even though older gccs do not). This trick suppresses the
+ * warning, but causes errors for plain gcc, so is only used in the one
+ * special case. */
+ static const union { __ULong __i[1]; float __d; } __Nanf = {0x7FC00000};
+ #define NAN (__Nanf.__d)
+ #else
+ #define NAN (0.0F/0.0F)
+ #endif
+ #endif
+
+#endif /* !gcc >= 3.3 */
+
+/* Reentrant ANSI C functions. */
+
+#ifndef __math_68881
+extern double atan _PARAMS((double));
+extern double cos _PARAMS((double));
+extern double sin _PARAMS((double));
+extern double tan _PARAMS((double));
+extern double tanh _PARAMS((double));
+extern double frexp _PARAMS((double, int *));
+extern double modf _PARAMS((double, double *));
+extern double ceil _PARAMS((double));
+extern double fabs _PARAMS((double));
+extern double floor _PARAMS((double));
+#endif /* ! defined (__math_68881) */
+
+/* Non reentrant ANSI C functions. */
+
+#ifndef _REENT_ONLY
+#ifndef __math_68881
+extern double acos _PARAMS((double));
+extern double asin _PARAMS((double));
+extern double atan2 _PARAMS((double, double));
+extern double cosh _PARAMS((double));
+extern double sinh _PARAMS((double));
+extern double exp _PARAMS((double));
+extern double ldexp _PARAMS((double, int));
+extern double log _PARAMS((double));
+extern double log10 _PARAMS((double));
+extern double pow _PARAMS((double, double));
+extern double sqrt _PARAMS((double));
+extern double fmod _PARAMS((double, double));
+#endif /* ! defined (__math_68881) */
+#endif /* ! defined (_REENT_ONLY) */
+
+#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L
+
+/* ISO C99 types and macros. */
+
+#ifndef FLT_EVAL_METHOD
+#define FLT_EVAL_METHOD 0
+typedef float float_t;
+typedef double double_t;
+#endif /* FLT_EVAL_METHOD */
+
+#define FP_NAN 0
+#define FP_INFINITE 1
+#define FP_ZERO 2
+#define FP_SUBNORMAL 3
+#define FP_NORMAL 4
+
+#ifndef FP_ILOGB0
+# define FP_ILOGB0 (-INT_MAX)
+#endif
+#ifndef FP_ILOGBNAN
+# define FP_ILOGBNAN INT_MAX
+#endif
+
+#ifndef MATH_ERRNO
+# define MATH_ERRNO 1
+#endif
+#ifndef MATH_ERREXCEPT
+# define MATH_ERREXCEPT 2
+#endif
+#ifndef math_errhandling
+# define math_errhandling MATH_ERRNO
+#endif
+
+extern int __isinff (float x);
+extern int __isinfd (double x);
+extern int __isnanf (float x);
+extern int __isnand (double x);
+extern int __fpclassifyf (float x);
+extern int __fpclassifyd (double x);
+extern int __signbitf (float x);
+extern int __signbitd (double x);
+
+#define fpclassify(__x) \
+ ((sizeof(__x) == sizeof(float)) ? __fpclassifyf(__x) : \
+ __fpclassifyd(__x))
+
+#ifndef isfinite
+ #define isfinite(__y) \
+ (__extension__ ({int __cy = fpclassify(__y); \
+ __cy != FP_INFINITE && __cy != FP_NAN;}))
+#endif
+
+/* Note: isinf and isnan were once functions in newlib that took double
+ * arguments. C99 specifies that these names are reserved for macros
+ * supporting multiple floating point types. Thus, they are
+ * now defined as macros. Implementations of the old functions
+ * taking double arguments still exist for compatibility purposes
+ * (prototypes for them are in <ieeefp.h>). */
+#ifndef isinf
+ #define isinf(y) (fpclassify(y) == FP_INFINITE)
+#endif
+
+#ifndef isnan
+ #define isnan(y) (fpclassify(y) == FP_NAN)
+#endif
+
+#define isnormal(y) (fpclassify(y) == FP_NORMAL)
+#define signbit(__x) \
+ ((sizeof(__x) == sizeof(float)) ? __signbitf(__x) : \
+ __signbitd(__x))
+
+#define isgreater(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x > __y);}))
+#define isgreaterequal(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x >= __y);}))
+#define isless(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x < __y);}))
+#define islessequal(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x <= __y);}))
+#define islessgreater(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x < __y || __x > __y);}))
+
+#define isunordered(a,b) \
+ (__extension__ ({__typeof__(a) __a = (a); __typeof__(b) __b = (b); \
+ fpclassify(__a) == FP_NAN || fpclassify(__b) == FP_NAN;}))
+
+/* Non ANSI double precision functions. */
+
+extern double infinity _PARAMS((void));
+extern double nan _PARAMS((const char *));
+extern int finite _PARAMS((double));
+extern double copysign _PARAMS((double, double));
+extern double logb _PARAMS((double));
+extern int ilogb _PARAMS((double));
+
+extern double asinh _PARAMS((double));
+extern double cbrt _PARAMS((double));
+extern double nextafter _PARAMS((double, double));
+extern double rint _PARAMS((double));
+extern double scalbn _PARAMS((double, int));
+
+extern double exp2 _PARAMS((double));
+extern double scalbln _PARAMS((double, long int));
+extern double tgamma _PARAMS((double));
+extern double nearbyint _PARAMS((double));
+extern long int lrint _PARAMS((double));
+extern _LONG_LONG_TYPE int llrint _PARAMS((double));
+extern double round _PARAMS((double));
+extern long int lround _PARAMS((double));
+extern long long int llround _PARAMS((double));
+extern double trunc _PARAMS((double));
+extern double remquo _PARAMS((double, double, int *));
+extern double fdim _PARAMS((double, double));
+extern double fmax _PARAMS((double, double));
+extern double fmin _PARAMS((double, double));
+extern double fma _PARAMS((double, double, double));
+
+#ifndef __math_68881
+extern double log1p _PARAMS((double));
+extern double expm1 _PARAMS((double));
+#endif /* ! defined (__math_68881) */
+
+#ifndef _REENT_ONLY
+extern double acosh _PARAMS((double));
+extern double atanh _PARAMS((double));
+extern double remainder _PARAMS((double, double));
+extern double gamma _PARAMS((double));
+extern double lgamma _PARAMS((double));
+extern double erf _PARAMS((double));
+extern double erfc _PARAMS((double));
+extern double log2 _PARAMS((double));
+#if !defined(__cplusplus)
+#define log2(x) (log (x) / _M_LN2)
+#endif
+
+#ifndef __math_68881
+extern double hypot _PARAMS((double, double));
+#endif
+
+#endif /* ! defined (_REENT_ONLY) */
+
+/* Single precision versions of ANSI functions. */
+
+extern float atanf _PARAMS((float));
+extern float cosf _PARAMS((float));
+extern float sinf _PARAMS((float));
+extern float tanf _PARAMS((float));
+extern float tanhf _PARAMS((float));
+extern float frexpf _PARAMS((float, int *));
+extern float modff _PARAMS((float, float *));
+extern float ceilf _PARAMS((float));
+extern float fabsf _PARAMS((float));
+extern float floorf _PARAMS((float));
+
+#ifndef _REENT_ONLY
+extern float acosf _PARAMS((float));
+extern float asinf _PARAMS((float));
+extern float atan2f _PARAMS((float, float));
+extern float coshf _PARAMS((float));
+extern float sinhf _PARAMS((float));
+extern float expf _PARAMS((float));
+extern float ldexpf _PARAMS((float, int));
+extern float logf _PARAMS((float));
+extern float log10f _PARAMS((float));
+extern float powf _PARAMS((float, float));
+extern float sqrtf _PARAMS((float));
+extern float fmodf _PARAMS((float, float));
+#endif /* ! defined (_REENT_ONLY) */
+
+/* Other single precision functions. */
+
+extern float exp2f _PARAMS((float));
+extern float scalblnf _PARAMS((float, long int));
+extern float tgammaf _PARAMS((float));
+extern float nearbyintf _PARAMS((float));
+extern long int lrintf _PARAMS((float));
+extern _LONG_LONG_TYPE llrintf _PARAMS((float));
+extern float roundf _PARAMS((float));
+extern long int lroundf _PARAMS((float));
+extern long long int llroundf _PARAMS((float));
+extern float truncf _PARAMS((float));
+extern float remquof _PARAMS((float, float, int *));
+extern float fdimf _PARAMS((float, float));
+extern float fmaxf _PARAMS((float, float));
+extern float fminf _PARAMS((float, float));
+extern float fmaf _PARAMS((float, float, float));
+
+extern float infinityf _PARAMS((void));
+extern float nanf _PARAMS((const char *));
+extern int finitef _PARAMS((float));
+extern float copysignf _PARAMS((float, float));
+extern float logbf _PARAMS((float));
+extern int ilogbf _PARAMS((float));
+
+extern float asinhf _PARAMS((float));
+extern float cbrtf _PARAMS((float));
+extern float nextafterf _PARAMS((float, float));
+extern float rintf _PARAMS((float));
+extern float scalbnf _PARAMS((float, int));
+extern float log1pf _PARAMS((float));
+extern float expm1f _PARAMS((float));
+
+#ifndef _REENT_ONLY
+extern float acoshf _PARAMS((float));
+extern float atanhf _PARAMS((float));
+extern float remainderf _PARAMS((float, float));
+extern float gammaf _PARAMS((float));
+extern float lgammaf _PARAMS((float));
+extern float erff _PARAMS((float));
+extern float erfcf _PARAMS((float));
+extern float log2f _PARAMS((float));
+#if !defined(__cplusplus)
+#define log2f(x) (logf (x) / (float_t) _M_LN2)
+#endif
+extern float hypotf _PARAMS((float, float));
+#endif /* ! defined (_REENT_ONLY) */
+
+/* On platforms where long double equals double. */
+#ifdef _LDBL_EQ_DBL
+/* Reentrant ANSI C functions. */
+#ifndef __math_68881
+extern long double atanl _PARAMS((long double));
+extern long double cosl _PARAMS((long double));
+extern long double sinl _PARAMS((long double));
+extern long double tanl _PARAMS((long double));
+extern long double tanhl _PARAMS((long double));
+extern long double frexpl _PARAMS((long double value, int *));
+extern long double modfl _PARAMS((long double, long double *));
+extern long double ceill _PARAMS((long double));
+extern long double fabsl _PARAMS((long double));
+extern long double floorl _PARAMS((long double));
+extern long double log1pl _PARAMS((long double));
+extern long double expm1l _PARAMS((long double));
+#endif /* ! defined (__math_68881) */
+/* Non reentrant ANSI C functions. */
+#ifndef _REENT_ONLY
+#ifndef __math_68881
+extern long double acosl _PARAMS((long double));
+extern long double asinl _PARAMS((long double));
+extern long double atan2l _PARAMS((long double, long double));
+extern long double coshl _PARAMS((long double));
+extern long double sinhl _PARAMS((long double));
+extern long double expl _PARAMS((long double));
+extern long double ldexpl _PARAMS((long double, int));
+extern long double logl _PARAMS((long double));
+extern long double log10l _PARAMS((long double));
+extern long double powl _PARAMS((long double, long double));
+extern long double sqrtl _PARAMS((long double));
+extern long double fmodl _PARAMS((long double, long double));
+extern long double hypotl _PARAMS((long double, long double));
+#endif /* ! defined (__math_68881) */
+#endif /* ! defined (_REENT_ONLY) */
+extern long double copysignl _PARAMS((long double, long double));
+extern long double nanl _PARAMS((const char *));
+extern int ilogbl _PARAMS((long double));
+extern long double asinhl _PARAMS((long double));
+extern long double cbrtl _PARAMS((long double));
+extern long double nextafterl _PARAMS((long double, long double));
+extern long double rintl _PARAMS((long double));
+extern long double scalbnl _PARAMS((long double, int));
+extern long double exp2l _PARAMS((long double));
+extern long double scalblnl _PARAMS((long double, long));
+extern long double tgammal _PARAMS((long double));
+extern long double nearbyintl _PARAMS((long double));
+extern long int lrintl _PARAMS((long double));
+extern long long int llrintl _PARAMS((long double));
+extern long double roundl _PARAMS((long double));
+extern long lroundl _PARAMS((long double));
+extern _LONG_LONG_TYPE int llroundl _PARAMS((long double));
+extern long double truncl _PARAMS((long double));
+extern long double remquol _PARAMS((long double, long double, int *));
+extern long double fdiml _PARAMS((long double, long double));
+extern long double fmaxl _PARAMS((long double, long double));
+extern long double fminl _PARAMS((long double, long double));
+extern long double fmal _PARAMS((long double, long double, long double));
+#ifndef _REENT_ONLY
+extern long double acoshl _PARAMS((long double));
+extern long double atanhl _PARAMS((long double));
+extern long double remainderl _PARAMS((long double, long double));
+extern long double lgammal _PARAMS((long double));
+extern long double erfl _PARAMS((long double));
+extern long double erfcl _PARAMS((long double));
+#endif /* ! defined (_REENT_ONLY) */
+#else /* !_LDBL_EQ_DBL */
+#ifdef __i386__
+/* Other long double precision functions. */
+extern _LONG_DOUBLE rintl _PARAMS((_LONG_DOUBLE));
+extern long int lrintl _PARAMS((_LONG_DOUBLE));
+extern _LONG_LONG_TYPE llrintl _PARAMS((_LONG_DOUBLE));
+#endif /* __i386__ */
+#endif /* !_LDBL_EQ_DBL */
+
+#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L */
+
+#if !defined (__STRICT_ANSI__) || defined(__cplusplus)
+
+extern double drem _PARAMS((double, double));
+extern void sincos _PARAMS((double, double *, double *));
+extern double gamma_r _PARAMS((double, int *));
+extern double lgamma_r _PARAMS((double, int *));
+
+extern double y0 _PARAMS((double));
+extern double y1 _PARAMS((double));
+extern double yn _PARAMS((int, double));
+extern double j0 _PARAMS((double));
+extern double j1 _PARAMS((double));
+extern double jn _PARAMS((int, double));
+
+extern float dremf _PARAMS((float, float));
+extern void sincosf _PARAMS((float, float *, float *));
+extern float gammaf_r _PARAMS((float, int *));
+extern float lgammaf_r _PARAMS((float, int *));
+
+extern float y0f _PARAMS((float));
+extern float y1f _PARAMS((float));
+extern float ynf _PARAMS((int, float));
+extern float j0f _PARAMS((float));
+extern float j1f _PARAMS((float));
+extern float jnf _PARAMS((int, float));
+
+/* GNU extensions */
+# ifndef exp10
+extern double exp10 _PARAMS((double));
+# endif
+# ifndef pow10
+extern double pow10 _PARAMS((double));
+# endif
+# ifndef exp10f
+extern float exp10f _PARAMS((float));
+# endif
+# ifndef pow10f
+extern float pow10f _PARAMS((float));
+# endif
+
+#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) */
+
+#ifndef __STRICT_ANSI__
+
+/* The gamma functions use a global variable, signgam. */
+#ifndef _REENT_ONLY
+#define signgam (*__signgam())
+extern int *__signgam _PARAMS((void));
+#endif /* ! defined (_REENT_ONLY) */
+
+#define __signgam_r(ptr) _REENT_SIGNGAM(ptr)
+
+/* The exception structure passed to the matherr routine. */
+/* We have a problem when using C++ since `exception' is a reserved
+ name in C++. */
+#ifdef __cplusplus
+struct __exception
+#else
+struct exception
+#endif
+{
+ int type;
+ char *name;
+ double arg1;
+ double arg2;
+ double retval;
+ int err;
+};
+
+#ifdef __cplusplus
+extern int matherr _PARAMS((struct __exception *e));
+#else
+extern int matherr _PARAMS((struct exception *e));
+#endif
+
+/* Values for the type field of struct exception. */
+
+#define DOMAIN 1
+#define SING 2
+#define OVERFLOW 3
+#define UNDERFLOW 4
+#define TLOSS 5
+#define PLOSS 6
+
+/* Useful constants. */
+
+#define MAXFLOAT 3.40282347e+38F
+
+#define M_E 2.7182818284590452354
+#define M_LOG2E 1.4426950408889634074
+#define M_LOG10E 0.43429448190325182765
+#define M_LN2 _M_LN2
+#define M_LN10 2.30258509299404568402
+#define M_PI 3.14159265358979323846
+#define M_TWOPI (M_PI * 2.0)
+#define M_PI_2 1.57079632679489661923
+#define M_PI_4 0.78539816339744830962
+#define M_3PI_4 2.3561944901923448370E0
+#define M_SQRTPI 1.77245385090551602792981
+#define M_1_PI 0.31830988618379067154
+#define M_2_PI 0.63661977236758134308
+#define M_2_SQRTPI 1.12837916709551257390
+#define M_SQRT2 1.41421356237309504880
+#define M_SQRT1_2 0.70710678118654752440
+#define M_LN2LO 1.9082149292705877000E-10
+#define M_LN2HI 6.9314718036912381649E-1
+#define M_SQRT3 1.73205080756887719000
+#define M_IVLN10 0.43429448190325182765 /* 1 / log(10) */
+#define M_LOG2_E _M_LN2
+#define M_INVLN2 1.4426950408889633870E0 /* 1 / log(2) */
+
+
+#define M_E_F 2.7182818284590452354f
+#define M_LOG2E_F 1.4426950408889634074f
+#define M_LOG10E_F 0.43429448190325182765f
+#define M_LN2_F _M_LN2_F
+#define M_LN10_F 2.30258509299404568402f
+#define M_PI_F 3.14159265358979323846f
+#define M_TWOPI_F (M_PI_F * 2.0f)
+#define M_PI_2_F 1.57079632679489661923f
+#define M_PI_4_F 0.78539816339744830962f
+#define M_3PI_4_F 2.3561944901923448370E0f
+#define M_SQRTPI_F 1.77245385090551602792981f
+#define M_1_PI_F 0.31830988618379067154f
+#define M_2_PI_F 0.63661977236758134308f
+#define M_2_SQRTPI_F 1.12837916709551257390f
+#define M_SQRT2_F 1.41421356237309504880f
+#define M_SQRT1_2_F 0.70710678118654752440f
+#define M_LN2LO_F 1.9082149292705877000E-10f
+#define M_LN2HI_F 6.9314718036912381649E-1f
+#define M_SQRT3_F 1.73205080756887719000f
+#define M_IVLN10_F 0.43429448190325182765f /* 1 / log(10) */
+#define M_LOG2_E_F _M_LN2_F
+#define M_INVLN2_F 1.4426950408889633870E0f /* 1 / log(2) */
+
+/* Global control over fdlibm error handling. */
+
+enum __fdlibm_version
+{
+ __fdlibm_ieee = -1,
+ __fdlibm_svid,
+ __fdlibm_xopen,
+ __fdlibm_posix
+};
+
+#define _LIB_VERSION_TYPE enum __fdlibm_version
+#define _LIB_VERSION __fdlib_version
+
+extern __IMPORT _LIB_VERSION_TYPE _LIB_VERSION;
+
+#define _IEEE_ __fdlibm_ieee
+#define _SVID_ __fdlibm_svid
+#define _XOPEN_ __fdlibm_xopen
+#define _POSIX_ __fdlibm_posix
+
+#endif /* ! defined (__STRICT_ANSI__) */
+
+_END_STD_C
+
+#ifdef __FAST_MATH__
+#include <machine/fastmath.h>
+#endif
+
+#endif /* _MATH_H_ */
diff --git a/nuttx/arch/arm/include/serial.h b/nuttx/arch/arm/include/serial.h
new file mode 100644
index 000000000..80eefb2b4
--- /dev/null
+++ b/nuttx/arch/arm/include/serial.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+ * arch/arm/include/serial.h
+ *
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_INCLUDE_SERIAL_H
+#define __ARCH_ARM_INCLUDE_SERIAL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+#include <nuttx/fs/ioctl.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#endif /* __ARCH_ARM_INCLUDE_SERIAL_H */
diff --git a/nuttx/arch/arm/include/stdarg.h b/nuttx/arch/arm/include/stdarg.h
new file mode 100644
index 000000000..653d34a6f
--- /dev/null
+++ b/nuttx/arch/arm/include/stdarg.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * arch/arm/include/stdarg.h
+ *
+ * Copyright (C) 2012 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_INCLUDE_STDARG_H
+#define __ARCH_ARM_INCLUDE_STDARG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* This should work with any modern gcc (newer than 3.4 or so) */
+
+#define va_start(v,l) __builtin_va_start(v,l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v,l) __builtin_va_arg(v,l)
+#define va_copy(d,s) __builtin_va_copy(d,s)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+typedef __builtin_va_list va_list;
+
+#endif /* __ARCH_ARM_INCLUDE_STDARG_H */
diff --git a/nuttx/arch/arm/include/stm32/chip.h b/nuttx/arch/arm/include/stm32/chip.h
new file mode 100644
index 000000000..2bf1d79b4
--- /dev/null
+++ b/nuttx/arch/arm/include/stm32/chip.h
@@ -0,0 +1,550 @@
+/************************************************************************************
+ * arch/arm/include/stm32/chip.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_INCLUDE_STM32_CHIP_H
+#define __ARCH_ARM_INCLUDE_STM32_CHIP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Get customizations for each supported chip and provide alternate function pin-mapping
+ *
+ * NOTE: Each GPIO pin may serve either for general purpose I/O or for a special
+ * alternate function (such as USART, CAN, USB, SDIO, etc.). That particular
+ * pin-mapping will depend on the package and STM32 family. If you are incorporating
+ * a new STM32 chip into NuttX, you will need to add the pin-mapping to a header file
+ * and to include that header file below. The chip-specific pin-mapping is defined in
+ * the chip datasheet.
+ */
+
+#if defined(CONFIG_ARCH_CHIP_STM32F100C8) || defined(CONFIG_ARCH_CHIP_STM32F100CB) \
+ || defined(CONFIG_ARCH_CHIP_STM32F100R8) || defined(CONFIG_ARCH_CHIP_STM32F100RB) \
+ || defined(CONFIG_ARCH_CHIP_STM32F100V8) || defined(CONFIG_ARCH_CHIP_STM32F100VB)
+# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F100x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# define CONFIG_STM32_MEDIUMDENSITY 1 /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# define CONFIG_STM32_VALUELINE 1 /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx families */
+# define STM32_NFSMC 0 /* FSMC */
+# define STM32_NATIM 1 /* One advanced timer TIM1 */
+# define STM32_NGTIM 3 /* 16-bit general timers TIM2,3,4 with DMA */
+# define STM32_NBTIM 0 /* No basic timers */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 2 /* SPI1-2 */
+# define STM32_NI2S 0 /* No I2S (?) */
+# define STM32_NUSART 3 /* USART1-3 */
+# define STM32_NI2C 2 /* I2C1-2 */
+# define STM32_NCAN 0 /* No CAN */
+# define STM32_NSDIO 0 /* No SDIO */
+# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */
+# define STM32_NGPIO 80 /* GPIOA-E */
+# define STM32_NADC 1 /* ADC1 */
+# define STM32_NDAC 2 /* DAC 1-2 */
+# define STM32_NCRC 1 /* CRC1 */
+# define STM32_NETHERNET 0 /* No ethernet */
+# define STM32_NRNG 0 /* No random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F103ZET6)
+# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# define CONFIG_STM32_HIGHDENSITY 1 /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx families */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 1 /* One advanced timer TIM1 */
+# define STM32_NGTIM 4 /* 16-bit generall timers TIM2,3,4,5 with DMA */
+# define STM32_NBTIM 0 /* No basic timers */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 2 /* SPI1-2 */
+# define STM32_NI2S 0 /* No I2S (?) */
+# define STM32_NUSART 3 /* USART1-3 */
+# define STM32_NI2C 2 /* I2C1-2 */
+# define STM32_NCAN 1 /* CAN1 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */
+# define STM32_NGPIO 112 /* GPIOA-G */
+# define STM32_NADC 1 /* ADC1 */
+# define STM32_NDAC 0 /* No DAC */
+# define STM32_NCRC 0 /* No CRC */
+# define STM32_NETHERNET 0 /* No ethernet */
+# define STM32_NRNG 0 /* No random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F103RET6)
+# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# define CONFIG_STM32_HIGHDENSITY 1 /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and TIM8 */
+# define STM32_NGTIM 4 /* 16-bit generall timers TIM2,3,4,5 with DMA */
+# define STM32_NBTIM 2 /* Two basic timers TIM6 and TIM7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 0 /* No I2S (?) */
+# define STM32_NUSART 5 /* USART1-5 */
+# define STM32_NI2C 2 /* I2C1-2 */
+# define STM32_NCAN 1 /* CAN1 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */
+# define STM32_NGPIO 51 /* GPIOA-D */
+# define STM32_NADC 2 /* ADC1-2 */
+# define STM32_NDAC 2 /* DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 0 /* No ethernet */
+# define STM32_NRNG 0 /* No random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F103VCT6)
+# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# define CONFIG_STM32_HIGHDENSITY 1 /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx families */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and TIM8 */
+# define STM32_NGTIM 4 /* General timers TIM2,3,4,5 */
+# define STM32_NBTIM 2 /* Two basic timers TIM6 and TIM7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 0 /* No I2S (?) */
+# define STM32_NUSART 5 /* USART1-5 */
+# define STM32_NI2C 2 /* I2C1-2 */
+# define STM32_NCAN 1 /* bxCAN1 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */
+# define STM32_NGPIO 80 /* GPIOA-E */
+# define STM32_NADC 3 /* ADC1-3 */
+# define STM32_NDAC 2 /* DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NTHERNET 0 /* No ethernet */
+# define STM32_NRNG 0 /* No random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F105VBT7)
+# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# define CONFIG_STM32_CONNECTIVITYLINE 1 /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 1 /* One advanced timers TIM1 */
+# define STM32_NGTIM 4 /* 16-bit generall timers TIM2,3,4,5 with DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 5 /* USART1-3, UART 4-5 */
+# define STM32_NI2C 2 /* I2C1-2 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 0 /* No SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 80 /* GPIOA-E */
+# define STM32_NADC 2 /* ADC1-2*/
+# define STM32_NDAC 2 /* DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 0 /* 100/100 Ethernet MAC */
+# define STM32_NRNG 0 /* No random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F107VC)
+# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# define CONFIG_STM32_CONNECTIVITYLINE 1 /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 1 /* One advanced timers TIM1 */
+# define STM32_NGTIM 4 /* 16-bit generall timers TIM2,3,4,5 with DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 5 /* USART1-3, UART 4-5 */
+# define STM32_NI2C 1 /* I2C1 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 0 /* No SDIO */
+# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */
+# define STM32_NGPIO 80 /* GPIOA-E */
+# define STM32_NADC 2 /* ADC1-2*/
+# define STM32_NDAC 2 /* DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */
+# define STM32_NRNG 0 /* No random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F207IG) /* UFBGA-176 1024Kb FLASH 128Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# define CONFIG_STM32_STM32F20XX 1 /* STM32F205x and STM32F207x */
+# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 140 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F405RG) /* LQFP 64 10x10x1.4 1024Kb FLASH 192Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 0 /* No FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 139 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 16 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 0 /* No Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F405VG) /* LQFP 100 14x14x1.4 1024Kb FLASH 192Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 139 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 16 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 0 /* No Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F405ZG) /* LQFP 144 20x20x1.4 1024Kb FLASH 192Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 139 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 0 /* No Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F407VE) /* LQFP-100 512Kb FLASH 192Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 139 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 16 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F407VG) /* LQFP-100 14x14x1.4 1024Kb FLASH 192Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 139 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 16 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F407ZE) /* LQFP-144 512Kb FLASH 192Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 139 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F407ZG) /* LQFP 144 20x20x1.4 1024Kb FLASH 192Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 139 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F407IE) /* LQFP 176 24x24x1.4 512Kb FLASH 192Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 (?) */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 139 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F407IG) /* BGA 176; LQFP 176 24x24x1.4 1024Kb FLASH 192Kb SRAM */
+# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F101x and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# define CONFIG_STM32_STM32F40XX 1 /* STM32F405xx and STM32407xx */
+# define STM32_NFSMC 1 /* FSMC */
+# define STM32_NATIM 2 /* Two advanced timers TIM1 and 8 */
+# define STM32_NGTIM 4 /* 16-bit general timers TIM3 and 4 with DMA
+ * 32-bit general timers TIM2 and 5 with DMA */
+# define STM32_NGTIMNDMA 6 /* 16-bit general timers TIM9-14 without DMA */
+# define STM32_NBTIM 2 /* Two basic timers, TIM6-7 */
+# define STM32_NDMA 2 /* DMA1-2 */
+# define STM32_NSPI 3 /* SPI1-3 */
+# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
+# define STM32_NUSART 6 /* USART1-3 and 6, UART 4-5 */
+# define STM32_NI2C 3 /* I2C1-3 */
+# define STM32_NCAN 2 /* CAN1-2 */
+# define STM32_NSDIO 1 /* SDIO */
+# define STM32_NUSBOTG 1 /* USB OTG FS/HS */
+# define STM32_NGPIO 139 /* GPIOA-I */
+# define STM32_NADC 3 /* 12-bit ADC1-3, 24 channels */
+# define STM32_NDAC 2 /* 12-bit DAC1-2 */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NETHERNET 1 /* 100/100 Ethernet MAC */
+# define STM32_NRNG 1 /* Random number generator (RNG) */
+# define STM32_NDCMI 1 /* Digital camera interface (DCMI) */
+
+#else
+# error "Unsupported STM32 chip"
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_STM32_CHIP_H */
+
diff --git a/nuttx/arch/arm/include/stm32/irq.h b/nuttx/arch/arm/include/stm32/irq.h
new file mode 100644
index 000000000..842183420
--- /dev/null
+++ b/nuttx/arch/arm/include/stm32/irq.h
@@ -0,0 +1,117 @@
+/************************************************************************************
+ * arch/arm/include/stm32s/irq.h
+ *
+ * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+/* This file should never be included directed but, rather,
+ * only indirectly through nuttx/irq.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_STM32_IRQ_H
+#define __ARCH_ARM_INCLUDE_STM32_IRQ_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/irq.h>
+#include <arch/stm32/chip.h>
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to
+ * bits in the NVIC. This does, however, waste several words of memory in the IRQ
+ * to handle mapping tables.
+ */
+
+/* Processor Exceptions (vectors 0-15) */
+
+#define STM32_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG) */
+ /* Vector 0: Reset stack pointer value */
+ /* Vector 1: Reset (not handler as an IRQ) */
+#define STM32_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */
+#define STM32_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */
+#define STM32_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */
+#define STM32_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */
+#define STM32_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */
+#define STM32_IRQ_SVCALL (11) /* Vector 11: SVC call */
+#define STM32_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */
+ /* Vector 13: Reserved */
+#define STM32_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */
+#define STM32_IRQ_SYSTICK (15) /* Vector 15: System tick */
+
+/* External interrupts (vectors >= 16). These definitions are chip-specific */
+
+#define STM32_IRQ_INTERRUPTS (16) /* Vector number of the first external interrupt */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include <arch/stm32/stm32f10xxx_irq.h>
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include <arch/stm32/stm32f20xxx_irq.h>
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include <arch/stm32/stm32f40xxx_irq.h>
+#else
+# error "Unsupported STM32 chip"
+#endif
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_STM32_IRQ_H */
+
diff --git a/nuttx/arch/arm/include/stm32/stm32f10xxx_irq.h b/nuttx/arch/arm/include/stm32/stm32f10xxx_irq.h
new file mode 100644
index 000000000..e9c495b78
--- /dev/null
+++ b/nuttx/arch/arm/include/stm32/stm32f10xxx_irq.h
@@ -0,0 +1,281 @@
+/************************************************************************************
+ * arch/arm/include/stm32s/stm32f10xxx_irq.h
+ *
+ * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+/* This file should never be included directed but, rather,
+ * only indirectly through nuttx/irq.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_STM32F10XXX_IRQ_H
+#define __ARCH_ARM_INCLUDE_STM32F10XXX_IRQ_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/irq.h>
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to
+ * bits in the NVIC. This does, however, waste several words of memory in the IRQ
+ * to handle mapping tables.
+ *
+ * Processor Exceptions (vectors 0-15). These common definitions can be found
+ * in nuttx/arch/arm/include/stm32/irq.h
+ *
+ * External interrupts (vectors >= 16)
+ */
+
+#if defined(CONFIG_STM32_VALUELINE) && defined(CONFIG_STM32_MEDIUMDENSITY)
+# define STM32_IRQ_WWDG (16) /* 0: Window Watchdog interrupt */
+# define STM32_IRQ_PVD (17) /* 1: PVD through EXTI Line detection interrupt */
+# define STM32_IRQ_TAMPER (18) /* 2: Tamper interrupt */
+# define STM32_IRQ_RTC (19) /* 3: RTC global interrupt */
+# define STM32_IRQ_FLASH (20) /* 4: Flash global interrupt */
+# define STM32_IRQ_RCC (21) /* 5: RCC global interrupt */
+# define STM32_IRQ_EXTI0 (22) /* 6: EXTI Line 0 interrupt */
+# define STM32_IRQ_EXTI1 (23) /* 7: EXTI Line 1 interrupt */
+# define STM32_IRQ_EXTI2 (24) /* 8: EXTI Line 2 interrupt */
+# define STM32_IRQ_EXTI3 (25) /* 9: EXTI Line 3 interrupt */
+# define STM32_IRQ_EXTI4 (26) /* 10: EXTI Line 4 interrupt */
+# define STM32_IRQ_DMA1CH1 (27) /* 11: DMA1 Channel 1 global interrupt */
+# define STM32_IRQ_DMA1CH2 (28) /* 12: DMA1 Channel 2 global interrupt */
+# define STM32_IRQ_DMA1CH3 (29) /* 13: DMA1 Channel 3 global interrupt */
+# define STM32_IRQ_DMA1CH4 (30) /* 14: DMA1 Channel 4 global interrupt */
+# define STM32_IRQ_DMA1CH5 (31) /* 15: DMA1 Channel 5 global interrupt */
+# define STM32_IRQ_DMA1CH6 (32) /* 16: DMA1 Channel 6 global interrupt */
+# define STM32_IRQ_DMA1CH7 (33) /* 17: DMA1 Channel 7 global interrupt */
+# define STM32_IRQ_ADC12 (34) /* 18: ADC1 and ADC2 global interrupt */
+ /* 19-22: reserved */
+# define STM32_IRQ_EXTI95 (39) /* 23: EXTI Line[9:5] interrupts */
+# define STM32_IRQ_TIM1BRK (40) /* 24: TIM1 Break interrupt */
+# define STM32_IRQ_TIM1UP (41) /* 25: TIM1 Update interrupt (TIM16 global interrupt) */
+# define STM32_IRQ_TIM1TRGCOM (42) /* 26: TIM1 Trigger and Commutation interrupts (TIM17 global interrupt) */
+# define STM32_IRQ_TIM1CC (43) /* 27: TIM1 Capture Compare interrupt */
+# define STM32_IRQ_TIM2 (44) /* 28: TIM2 global interrupt */
+# define STM32_IRQ_TIM3 (45) /* 29: TIM3 global interrupt */
+# define STM32_IRQ_TIM4 (46) /* 30: TIM4 global interrupt */
+# define STM32_IRQ_I2C1EV (47) /* 31: I2C1 event interrupt */
+# define STM32_IRQ_I2C1ER (48) /* 32: I2C1 error interrupt */
+# define STM32_IRQ_I2C2EV (49) /* 33: I2C2 event interrupt */
+# define STM32_IRQ_I2C2ER (50) /* 34: I2C2 error interrupt */
+# define STM32_IRQ_SPI1 (51) /* 35: SPI1 global interrupt */
+# define STM32_IRQ_SPI2 (52) /* 36: SPI2 global interrupt */
+# define STM32_IRQ_USART1 (53) /* 37: USART1 global interrupt */
+# define STM32_IRQ_USART2 (54) /* 38: USART2 global interrupt */
+# define STM32_IRQ_USART3 (55) /* 39: USART3 global interrupt */
+# define STM32_IRQ_EXTI1510 (56) /* 40: EXTI Line[15:10] interrupts */
+# define STM32_IRQ_RTCALR (57) /* 41: RTC alarm through EXTI line interrupt */
+# define STM32_IRQ_CEC (58) /* 42: CEC global interrupt */
+# if defined(CONFIG_STM32_HIGHDENSITY)
+# define STM32_IRQ_TIM12 (59) /* 43: TIM12 global interrupt */
+# define STM32_IRQ_TIM13 (60) /* 44: TIM13 global interrupt */
+# define STM32_IRQ_TIM14 (61) /* 45: TIM14 global interrupt */
+ /* 46-47: reserved */
+# define STM32_IRQ_FSMC (64) /* 48: FSMC global interrupt */
+ /* 49: reserved */
+# define STM32_IRQ_TIM5 (66) /* 50: TIM5 global interrupt */
+# define STM32_IRQ_SPI3 (67) /* 51: SPI1 global interrupt */
+# define STM32_IRQ_UART4 (68) /* 52: USART2 global interrupt */
+# define STM32_IRQ_UART5 (69) /* 53: USART3 global interrupt */
+# else
+ /* 43-53: reserved */
+# endif
+# define STM32_IRQ_TIM6 (70) /* 54: TIM6 global interrupt */
+# define STM32_IRQ_TIM7 (71) /* 55: TIM7 global interrupt */
+# define STM32_IRQ_DMA2CH1 (72) /* 56: DMA2 Channel 1 global interrupt */
+# define STM32_IRQ_DMA2CH2 (73) /* 57: DMA2 Channel 2 global interrupt */
+# define STM32_IRQ_DMA2CH3 (74) /* 58: DMA2 Channel 3 global interrupt */
+# define STM32_IRQ_DMA2CH45 (75) /* 59: DMA2 Channel 4 global interrupt */
+# define NR_IRQS (76)
+#elif defined(CONFIG_STM32_CONNECTIVITYLINE)
+# define STM32_IRQ_WWDG (16) /* 0: Window Watchdog interrupt */
+# define STM32_IRQ_PVD (17) /* 1: PVD through EXTI Line detection interrupt */
+# define STM32_IRQ_TAMPER (18) /* 2: Tamper interrupt */
+# define STM32_IRQ_RTC (19) /* 3: RTC global interrupt */
+# define STM32_IRQ_FLASH (20) /* 4: Flash global interrupt */
+# define STM32_IRQ_RCC (21) /* 5: RCC global interrupt */
+# define STM32_IRQ_EXTI0 (22) /* 6: EXTI Line 0 interrupt */
+# define STM32_IRQ_EXTI1 (23) /* 7: EXTI Line 1 interrupt */
+# define STM32_IRQ_EXTI2 (24) /* 8: EXTI Line 2 interrupt */
+# define STM32_IRQ_EXTI3 (25) /* 9: EXTI Line 3 interrupt */
+# define STM32_IRQ_EXTI4 (26) /* 10: EXTI Line 4 interrupt */
+# define STM32_IRQ_DMA1CH1 (27) /* 11: DMA1 Channel 1 global interrupt */
+# define STM32_IRQ_DMA1CH2 (28) /* 12: DMA1 Channel 2 global interrupt */
+# define STM32_IRQ_DMA1CH3 (29) /* 13: DMA1 Channel 3 global interrupt */
+# define STM32_IRQ_DMA1CH4 (30) /* 14: DMA1 Channel 4 global interrupt */
+# define STM32_IRQ_DMA1CH5 (31) /* 15: DMA1 Channel 5 global interrupt */
+# define STM32_IRQ_DMA1CH6 (32) /* 16: DMA1 Channel 6 global interrupt */
+# define STM32_IRQ_DMA1CH7 (33) /* 17: DMA1 Channel 7 global interrupt */
+# define STM32_IRQ_ADC12 (34) /* 18: ADC1 and ADC2 global interrupt */
+# define STM32_IRQ_CAN1TX (35) /* 19: CAN1 TX interrupts */
+# define STM32_IRQ_CAN1RX0 (36) /* 20: CAN1 RX0 interrupts */
+# define STM32_IRQ_CAN1RX1 (37) /* 21: CAN1 RX1 interrupt */
+# define STM32_IRQ_CAN1SCE (38) /* 22: CAN1 SCE interrupt */
+# define STM32_IRQ_EXTI95 (39) /* 23: EXTI Line[9:5] interrupts */
+# define STM32_IRQ_TIM1BRK (40) /* 24: TIM1 Break interrupt */
+# define STM32_IRQ_TIM1UP (41) /* 25: TIM1 Update interrupt */
+# define STM32_IRQ_TIM1TRGCOM (42) /* 26: TIM1 Trigger and Commutation interrupts */
+# define STM32_IRQ_TIM1CC (43) /* 27: TIM1 Capture Compare interrupt */
+# define STM32_IRQ_TIM2 (44) /* 28: TIM2 global interrupt */
+# define STM32_IRQ_TIM3 (45) /* 29: TIM3 global interrupt */
+# define STM32_IRQ_TIM4 (46) /* 30: TIM4 global interrupt */
+# define STM32_IRQ_I2C1EV (47) /* 31: I2C1 event interrupt */
+# define STM32_IRQ_I2C1ER (48) /* 32: I2C1 error interrupt */
+# define STM32_IRQ_I2C2EV (49) /* 33: I2C2 event interrupt */
+# define STM32_IRQ_I2C2ER (50) /* 34: I2C2 error interrupt */
+# define STM32_IRQ_SPI1 (51) /* 35: SPI1 global interrupt */
+# define STM32_IRQ_SPI2 (52) /* 36: SPI2 global interrupt */
+# define STM32_IRQ_USART1 (53) /* 37: USART1 global interrupt */
+# define STM32_IRQ_USART2 (54) /* 38: USART2 global interrupt */
+# define STM32_IRQ_USART3 (55) /* 39: USART3 global interrupt */
+# define STM32_IRQ_EXTI1510 (56) /* 40: EXTI Line[15:10] interrupts */
+# define STM32_IRQ_RTCALRM (57) /* 41: RTC alarm through EXTI line interrupt */
+# define STM32_IRQ_OTGFSWKUP (58) /* 42: USB On-The-Go FS Wakeup through EXTI line interrupt */
+ /* 43-49: Reserved */
+# define STM32_IRQ_TIM5 (66) /* 50: TIM5 global interrupt */
+# define STM32_IRQ_SPI3 (67) /* 51: SPI3 global interrupt */
+# define STM32_IRQ_UART4 (68) /* 52: UART4 global interrupt */
+# define STM32_IRQ_UART5 (69) /* 53: UART5 global interrupt */
+# define STM32_IRQ_TIM6 (70) /* 54: TIM6 global interrupt */
+# define STM32_IRQ_TIM7 (71) /* 55: TIM7 global interrupt */
+# define STM32_IRQ_DMA2CH1 (72) /* 56: DMA2 Channel 1 global interrupt */
+# define STM32_IRQ_DMA2CH2 (73) /* 57: DMA2 Channel 2 global interrupt */
+# define STM32_IRQ_DMA2CH3 (74) /* 58: DMA2 Channel 3 global interrupt */
+# define STM32_IRQ_DMA2CH4 (75) /* 59: DMA2 Channel 4 global interrupt */
+# define STM32_IRQ_DMA2CH5 (76) /* 60: DMA2 Channel 5 global interrupt */
+# define STM32_IRQ_ETH (77) /* 61: Ethernet global interrupt */
+# define STM32_IRQ_ETHWKUP (78) /* 62: Ethernet Wakeup through EXTI line interrupt */
+# define STM32_IRQ_CAN2TX (79) /* 63: CAN2 TX interrupts */
+# define STM32_IRQ_CAN2RX0 (70) /* 64: CAN2 RX0 interrupts */
+# define STM32_IRQ_CAN2RX1 (81) /* 65: CAN2 RX1 interrupt */
+# define STM32_IRQ_CAN2SCE (82) /* 66: CAN2 SCE interrupt */
+# define STM32_IRQ_OTGFS (83) /* 67: USB On The Go FS global interrupt */
+# define NR_IRQS (84)
+#else
+# define STM32_IRQ_WWDG (16) /* 0: Window Watchdog interrupt */
+# define STM32_IRQ_PVD (17) /* 1: PVD through EXTI Line detection interrupt */
+# define STM32_IRQ_TAMPER (18) /* 2: Tamper interrupt */
+# define STM32_IRQ_RTC (19) /* 3: RTC global interrupt */
+# define STM32_IRQ_FLASH (20) /* 4: Flash global interrupt */
+# define STM32_IRQ_RCC (21) /* 5: RCC global interrupt */
+# define STM32_IRQ_EXTI0 (22) /* 6: EXTI Line 0 interrupt */
+# define STM32_IRQ_EXTI1 (23) /* 7: EXTI Line 1 interrupt */
+# define STM32_IRQ_EXTI2 (24) /* 8: EXTI Line 2 interrupt */
+# define STM32_IRQ_EXTI3 (25) /* 9: EXTI Line 3 interrupt */
+# define STM32_IRQ_EXTI4 (26) /* 10: EXTI Line 4 interrupt */
+# define STM32_IRQ_DMA1CH1 (27) /* 11: DMA1 Channel 1 global interrupt */
+# define STM32_IRQ_DMA1CH2 (28) /* 12: DMA1 Channel 2 global interrupt */
+# define STM32_IRQ_DMA1CH3 (29) /* 13: DMA1 Channel 3 global interrupt */
+# define STM32_IRQ_DMA1CH4 (30) /* 14: DMA1 Channel 4 global interrupt */
+# define STM32_IRQ_DMA1CH5 (31) /* 15: DMA1 Channel 5 global interrupt */
+# define STM32_IRQ_DMA1CH6 (32) /* 16: DMA1 Channel 6 global interrupt */
+# define STM32_IRQ_DMA1CH7 (33) /* 17: DMA1 Channel 7 global interrupt */
+# define STM32_IRQ_ADC12 (34) /* 18: ADC1 and ADC2 global interrupt */
+# define STM32_IRQ_USBHPCANTX (35) /* 19: USB High Priority or CAN TX interrupts*/
+# define STM32_IRQ_USBLPCANRX0 (36) /* 20: USB Low Priority or CAN RX0 interrupts*/
+# define STM32_IRQ_CAN1RX1 (37) /* 21: CAN1 RX1 interrupt */
+# define STM32_IRQ_CAN1SCE (38) /* 22: CAN1 SCE interrupt */
+# define STM32_IRQ_EXTI95 (39) /* 23: EXTI Line[9:5] interrupts */
+# define STM32_IRQ_TIM1BRK (40) /* 24: TIM1 Break interrupt */
+# define STM32_IRQ_TIM1UP (41) /* 25: TIM1 Update interrupt */
+# define STM32_IRQ_TIM1TRGCOM (42) /* 26: TIM1 Trigger and Commutation interrupts */
+# define STM32_IRQ_TIM1CC (43) /* 27: TIM1 Capture Compare interrupt */
+# define STM32_IRQ_TIM2 (44) /* 28: TIM2 global interrupt */
+# define STM32_IRQ_TIM3 (45) /* 29: TIM3 global interrupt */
+# define STM32_IRQ_TIM4 (46) /* 30: TIM4 global interrupt */
+# define STM32_IRQ_I2C1EV (47) /* 31: I2C1 event interrupt */
+# define STM32_IRQ_I2C1ER (48) /* 32: I2C1 error interrupt */
+# define STM32_IRQ_I2C2EV (49) /* 33: I2C2 event interrupt */
+# define STM32_IRQ_I2C2ER (50) /* 34: I2C2 error interrupt */
+# define STM32_IRQ_SPI1 (51) /* 35: SPI1 global interrupt */
+# define STM32_IRQ_SPI2 (52) /* 36: SPI2 global interrupt */
+# define STM32_IRQ_USART1 (53) /* 37: USART1 global interrupt */
+# define STM32_IRQ_USART2 (54) /* 38: USART2 global interrupt */
+# define STM32_IRQ_USART3 (55) /* 39: USART3 global interrupt */
+# define STM32_IRQ_EXTI1510 (56) /* 40: EXTI Line[15:10] interrupts */
+# define STM32_IRQ_RTCALRM (57) /* 41: RTC alarm through EXTI line interrupt */
+# define STM32_IRQ_USBWKUP (58) /* 42: USB wakeup from suspend through EXTI line interrupt*/
+# define STM32_IRQ_TIM8BRK (59) /* 43: TIM8 Break interrupt */
+# define STM32_IRQ_TIM8UP (60) /* 44: TIM8 Update interrupt */
+# define STM32_IRQ_TIM8TRGCOM (61) /* 45: TIM8 Trigger and Commutation interrupts */
+# define STM32_IRQ_TIM8CC (62) /* 46: TIM8 Capture Compare interrupt */
+# define STM32_IRQ_ADC3 (63) /* 47: ADC3 global interrupt */
+# define STM32_IRQ_FSMC (64) /* 48: FSMC global interrupt */
+# define STM32_IRQ_SDIO (65) /* 49: SDIO global interrupt */
+# define STM32_IRQ_TIM5 (66) /* 50: TIM5 global interrupt */
+# define STM32_IRQ_SPI3 (67) /* 51: SPI3 global interrupt */
+# define STM32_IRQ_UART4 (68) /* 52: UART4 global interrupt */
+# define STM32_IRQ_UART5 (69) /* 53: UART5 global interrupt */
+# define STM32_IRQ_TIM6 (70) /* 54: TIM6 global interrupt */
+# define STM32_IRQ_TIM7 (71) /* 55: TIM7 global interrupt */
+# define STM32_IRQ_DMA2CH1 (72) /* 56: DMA2 Channel 1 global interrupt */
+# define STM32_IRQ_DMA2CH2 (73) /* 57: DMA2 Channel 2 global interrupt */
+# define STM32_IRQ_DMA2CH3 (74) /* 58: DMA2 Channel 3 global interrupt */
+# define STM32_IRQ_DMA2CH45 (75) /* 59: DMA2 Channel 4&5 global interrupt */
+# define NR_IRQS (76)
+#endif
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_STM32F10XXX_IRQ_H */
+
diff --git a/nuttx/arch/arm/include/stm32/stm32f20xxx_irq.h b/nuttx/arch/arm/include/stm32/stm32f20xxx_irq.h
new file mode 100644
index 000000000..d88c5d070
--- /dev/null
+++ b/nuttx/arch/arm/include/stm32/stm32f20xxx_irq.h
@@ -0,0 +1,182 @@
+/****************************************************************************************************
+ * arch/arm/include/stm32s/stm32f20xxx_irq.h
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************************************/
+
+/* This file should never be included directed but, rather, only indirectly through nuttx/irq.h */
+
+#ifndef __ARCH_ARM_INCLUDE_STM32F20XXX_IRQ_H
+#define __ARCH_ARM_INCLUDE_STM32F20XXX_IRQ_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/irq.h>
+
+/****************************************************************************************************
+ * Definitions
+ ****************************************************************************************************/
+
+/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to
+ * bits in the NVIC. This does, however, waste several words of memory in the IRQ
+ * to handle mapping tables.
+ *
+ * Processor Exceptions (vectors 0-15). These common definitions can be found
+ * in nuttx/arch/arm/include/stm32/irq.h
+ *
+ * External interrupts (vectors >= 16)
+ */
+
+#define STM32_IRQ_WWDG (STM32_IRQ_INTERRUPTS+0) /* 0: Window Watchdog interrupt */
+#define STM32_IRQ_PVD (STM32_IRQ_INTERRUPTS+1) /* 1: PVD through EXTI Line detection interrupt */
+#define STM32_IRQ_TAMPER (STM32_IRQ_INTERRUPTS+2) /* 2: Tamper and time stamp interrupts */
+#define STM32_IRQ_TIMESTAMP (STM32_IRQ_INTERRUPTS+2) /* 2: Tamper and time stamp interrupts */
+#define STM32_IRQ_RTC_WKUP (STM32_IRQ_INTERRUPTS+3) /* 3: RTC global interrupt */
+#define STM32_IRQ_FLASH (STM32_IRQ_INTERRUPTS+4) /* 4: Flash global interrupt */
+#define STM32_IRQ_RCC (STM32_IRQ_INTERRUPTS+5) /* 5: RCC global interrupt */
+#define STM32_IRQ_EXTI0 (STM32_IRQ_INTERRUPTS+6) /* 6: EXTI Line 0 interrupt */
+#define STM32_IRQ_EXTI1 (STM32_IRQ_INTERRUPTS+7) /* 7: EXTI Line 1 interrupt */
+#define STM32_IRQ_EXTI2 (STM32_IRQ_INTERRUPTS+8) /* 8: EXTI Line 2 interrupt */
+#define STM32_IRQ_EXTI3 (STM32_IRQ_INTERRUPTS+9) /* 9: EXTI Line 3 interrupt */
+#define STM32_IRQ_EXTI4 (STM32_IRQ_INTERRUPTS+10) /* 10: EXTI Line 4 interrupt */
+#define STM32_IRQ_DMA1S0 (STM32_IRQ_INTERRUPTS+11) /* 11: DMA1 Stream 0 global interrupt */
+#define STM32_IRQ_DMA1S1 (STM32_IRQ_INTERRUPTS+12) /* 12: DMA1 Stream 1 global interrupt */
+#define STM32_IRQ_DMA1S2 (STM32_IRQ_INTERRUPTS+13) /* 13: DMA1 Stream 2 global interrupt */
+#define STM32_IRQ_DMA1S3 (STM32_IRQ_INTERRUPTS+14) /* 14: DMA1 Stream 3 global interrupt */
+#define STM32_IRQ_DMA1S4 (STM32_IRQ_INTERRUPTS+15) /* 15: DMA1 Stream 4 global interrupt */
+#define STM32_IRQ_DMA1S5 (STM32_IRQ_INTERRUPTS+16) /* 16: DMA1 Stream 5 global interrupt */
+#define STM32_IRQ_DMA1S6 (STM32_IRQ_INTERRUPTS+17) /* 17: DMA1 Stream 6 global interrupt */
+#define STM32_IRQ_ADC (STM32_IRQ_INTERRUPTS+18) /* 18: ADC1, ADC2, and ADC3 global interrupt */
+#define STM32_IRQ_CAN1TX (STM32_IRQ_INTERRUPTS+19) /* 19: CAN1 TX interrupts */
+#define STM32_IRQ_CAN1RX0 (STM32_IRQ_INTERRUPTS+20) /* 20: CAN1 RX0 interrupts */
+#define STM32_IRQ_CAN1RX1 (STM32_IRQ_INTERRUPTS+21) /* 21: CAN1 RX1 interrupt */
+#define STM32_IRQ_CAN1SCE (STM32_IRQ_INTERRUPTS+22) /* 22: CAN1 SCE interrupt */
+#define STM32_IRQ_EXTI95 (STM32_IRQ_INTERRUPTS+23) /* 23: EXTI Line[9:5] interrupts */
+#define STM32_IRQ_TIM1BRK (STM32_IRQ_INTERRUPTS+24) /* 24: TIM1 Break interrupt */
+#define STM32_IRQ_TIM9 (STM32_IRQ_INTERRUPTS+24) /* 24: TIM9 global interrupt */
+#define STM32_IRQ_TIM1UP (STM32_IRQ_INTERRUPTS+25) /* 25: TIM1 Update interrupt */
+#define STM32_IRQ_TIM10 (STM32_IRQ_INTERRUPTS+25) /* 25: TIM10 global interrupt */
+#define STM32_IRQ_TIM1TRGCOM (STM32_IRQ_INTERRUPTS+26) /* 26: TIM1 Trigger and Commutation interrupts */
+#define STM32_IRQ_TIM11 (STM32_IRQ_INTERRUPTS+26) /* 26: TIM11 global interrupt */
+#define STM32_IRQ_TIM1CC (STM32_IRQ_INTERRUPTS+27) /* 27: TIM1 Capture Compare interrupt */
+#define STM32_IRQ_TIM2 (STM32_IRQ_INTERRUPTS+28) /* 28: TIM2 global interrupt */
+#define STM32_IRQ_TIM3 (STM32_IRQ_INTERRUPTS+29) /* 29: TIM3 global interrupt */
+#define STM32_IRQ_TIM4 (STM32_IRQ_INTERRUPTS+30) /* 30: TIM4 global interrupt */
+#define STM32_IRQ_I2C1EV (STM32_IRQ_INTERRUPTS+31) /* 31: I2C1 event interrupt */
+#define STM32_IRQ_I2C1ER (STM32_IRQ_INTERRUPTS+32) /* 32: I2C1 error interrupt */
+#define STM32_IRQ_I2C2EV (STM32_IRQ_INTERRUPTS+33) /* 33: I2C2 event interrupt */
+#define STM32_IRQ_I2C2ER (STM32_IRQ_INTERRUPTS+34) /* 34: I2C2 error interrupt */
+#define STM32_IRQ_SPI1 (STM32_IRQ_INTERRUPTS+35) /* 35: SPI1 global interrupt */
+#define STM32_IRQ_SPI2 (STM32_IRQ_INTERRUPTS+36) /* 36: SPI2 global interrupt */
+#define STM32_IRQ_USART1 (STM32_IRQ_INTERRUPTS+37) /* 37: USART1 global interrupt */
+#define STM32_IRQ_USART2 (STM32_IRQ_INTERRUPTS+38) /* 38: USART2 global interrupt */
+#define STM32_IRQ_USART3 (STM32_IRQ_INTERRUPTS+39) /* 39: USART3 global interrupt */
+#define STM32_IRQ_EXTI1510 (STM32_IRQ_INTERRUPTS+40) /* 40: EXTI Line[15:10] interrupts */
+#define STM32_IRQ_RTCALRM (STM32_IRQ_INTERRUPTS+41) /* 41: RTC alarm through EXTI line interrupt */
+#define STM32_IRQ_OTGFSWKUP (STM32_IRQ_INTERRUPTS+42) /* 42: USB On-The-Go FS Wakeup through EXTI line interrupt */
+#define STM32_IRQ_TIM8BRK (STM32_IRQ_INTERRUPTS+43) /* 43: TIM8 Break interrupt */
+#define STM32_IRQ_TIM12 (STM32_IRQ_INTERRUPTS+43) /* 43: TIM12 global interrupt */
+#define STM32_IRQ_TIM8UP (STM32_IRQ_INTERRUPTS+44) /* 44: TIM8 Update interrupt */
+#define STM32_IRQ_TIM13 (STM32_IRQ_INTERRUPTS+44) /* 44: TIM13 global interrupt */
+#define STM32_IRQ_TIM8TRGCOM (STM32_IRQ_INTERRUPTS+45) /* 45: TIM8 Trigger and Commutation interrupts */
+#define STM32_IRQ_TIM14 (STM32_IRQ_INTERRUPTS+45) /* 45: TIM14 global interrupt */
+#define STM32_IRQ_TIM8CC (STM32_IRQ_INTERRUPTS+46) /* 46: TIM8 Capture Compare interrupt */
+#define STM32_IRQ_DMA1S7 (STM32_IRQ_INTERRUPTS+47) /* 47: DMA1 Stream 7 global interrupt */
+#define STM32_IRQ_FSMC (STM32_IRQ_INTERRUPTS+48) /* 48: FSMC global interrupt */
+#define STM32_IRQ_SDIO (STM32_IRQ_INTERRUPTS+49) /* 49: SDIO global interrupt */
+#define STM32_IRQ_TIM5 (STM32_IRQ_INTERRUPTS+50) /* 50: TIM5 global interrupt */
+#define STM32_IRQ_SPI3 (STM32_IRQ_INTERRUPTS+51) /* 51: SPI3 global interrupt */
+#define STM32_IRQ_UART4 (STM32_IRQ_INTERRUPTS+52) /* 52: UART4 global interrupt */
+#define STM32_IRQ_UART5 (STM32_IRQ_INTERRUPTS+53) /* 53: UART5 global interrupt */
+#define STM32_IRQ_TIM6 (STM32_IRQ_INTERRUPTS+54) /* 54: TIM6 global interrupt */
+#define STM32_IRQ_DAC (STM32_IRQ_INTERRUPTS+54) /* 54: DAC1 and DAC2 underrun error interrupts */
+#define STM32_IRQ_TIM7 (STM32_IRQ_INTERRUPTS+55) /* 55: TIM7 global interrupt */
+#define STM32_IRQ_DMA2S0 (STM32_IRQ_INTERRUPTS+56) /* 56: DMA2 Stream 0 global interrupt */
+#define STM32_IRQ_DMA2S1 (STM32_IRQ_INTERRUPTS+57) /* 57: DMA2 Stream 1 global interrupt */
+#define STM32_IRQ_DMA2S2 (STM32_IRQ_INTERRUPTS+58) /* 58: DMA2 Stream 2 global interrupt */
+#define STM32_IRQ_DMA2S3 (STM32_IRQ_INTERRUPTS+59) /* 59: DMA2 Stream 3 global interrupt */
+#define STM32_IRQ_DMA2S4 (STM32_IRQ_INTERRUPTS+60) /* 60: DMA2 Stream 4 global interrupt */
+#define STM32_IRQ_ETH (STM32_IRQ_INTERRUPTS+61) /* 61: Ethernet global interrupt */
+#define STM32_IRQ_ETHWKUP (STM32_IRQ_INTERRUPTS+62) /* 62: Ethernet Wakeup through EXTI line interrupt */
+#define STM32_IRQ_CAN2TX (STM32_IRQ_INTERRUPTS+63) /* 63: CAN2 TX interrupts */
+#define STM32_IRQ_CAN2RX0 (STM32_IRQ_INTERRUPTS+64) /* 64: CAN2 RX0 interrupts */
+#define STM32_IRQ_CAN2RX1 (STM32_IRQ_INTERRUPTS+65) /* 65: CAN2 RX1 interrupt */
+#define STM32_IRQ_CAN2SCE (STM32_IRQ_INTERRUPTS+66) /* 66: CAN2 SCE interrupt */
+#define STM32_IRQ_OTGFS (STM32_IRQ_INTERRUPTS+67) /* 67: USB On The Go FS global interrupt */
+#define STM32_IRQ_DMA2S5 (STM32_IRQ_INTERRUPTS+68) /* 68: DMA2 Stream 5 global interrupt */
+#define STM32_IRQ_DMA2S6 (STM32_IRQ_INTERRUPTS+69) /* 69: DMA2 Stream 6 global interrupt */
+#define STM32_IRQ_DMA2S7 (STM32_IRQ_INTERRUPTS+70) /* 70: DMA2 Stream 7 global interrupt */
+#define STM32_IRQ_USART6 (STM32_IRQ_INTERRUPTS+71) /* 71: USART6 global interrupt */
+#define STM32_IRQ_I2C3EV (STM32_IRQ_INTERRUPTS+72) /* 72: I2C3 event interrupt */
+#define STM32_IRQ_I2C3ER (STM32_IRQ_INTERRUPTS+73) /* 73: I2C3 error interrupt */
+#define STM32_IRQ_OTGHSEP1OUT (STM32_IRQ_INTERRUPTS+74) /* 74: USB On The Go HS End Point 1 Out global interrupt */
+#define STM32_IRQ_OTGHSEP1IN (STM32_IRQ_INTERRUPTS+75) /* 75: USB On The Go HS End Point 1 In global interrupt */
+#define STM32_IRQ_OTGHSWKUP (STM32_IRQ_INTERRUPTS+76) /* 76: USB On The Go HS Wakeup through EXTI interrupt */
+#define STM32_IRQ_OTGHS (STM32_IRQ_INTERRUPTS+77) /* 77: USB On The Go HS global interrupt */
+#define STM32_IRQ_DCMI (STM32_IRQ_INTERRUPTS+78) /* 78: DCMI global interrupt */
+#define STM32_IRQ_CRYP (STM32_IRQ_INTERRUPTS+79) /* 79: CRYP crypto global interrupt */
+#define STM32_IRQ_HASH (STM32_IRQ_INTERRUPTS+80) /* 80: Hash and Rng global interrupt */
+#define STM32_IRQ_RNG (STM32_IRQ_INTERRUPTS+80) /* 80: Hash and Rng global interrupt */
+
+#define NR_IRQS (STM32_IRQ_INTERRUPTS+81)
+
+/****************************************************************************************************
+ * Public Types
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Public Data
+****************************************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************************************
+ * Public Functions
+ ****************************************************************************************************/
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_STM32F40XXX_IRQ_H */
+
diff --git a/nuttx/arch/arm/include/stm32/stm32f40xxx_irq.h b/nuttx/arch/arm/include/stm32/stm32f40xxx_irq.h
new file mode 100644
index 000000000..cd97b9c9d
--- /dev/null
+++ b/nuttx/arch/arm/include/stm32/stm32f40xxx_irq.h
@@ -0,0 +1,185 @@
+/****************************************************************************************************
+ * arch/arm/include/stm32s/stm32f40xxx_irq.h
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************************************/
+
+/* This file should never be included directed but, rather,
+ * only indirectly through nuttx/irq.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_STM32F40XXX_IRQ_H
+#define __ARCH_ARM_INCLUDE_STM32F40XXX_IRQ_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/irq.h>
+
+/****************************************************************************************************
+ * Definitions
+ ****************************************************************************************************/
+
+/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to
+ * bits in the NVIC. This does, however, waste several words of memory in the IRQ
+ * to handle mapping tables.
+ *
+ * Processor Exceptions (vectors 0-15). These common definitions can be found
+ * in nuttx/arch/arm/include/stm32/irq.h
+ *
+ * External interrupts (vectors >= 16)
+ */
+
+#define STM32_IRQ_WWDG (STM32_IRQ_INTERRUPTS+0) /* 0: Window Watchdog interrupt */
+#define STM32_IRQ_PVD (STM32_IRQ_INTERRUPTS+1) /* 1: PVD through EXTI Line detection interrupt */
+#define STM32_IRQ_TAMPER (STM32_IRQ_INTERRUPTS+2) /* 2: Tamper and time stamp interrupts */
+#define STM32_IRQ_TIMESTAMP (STM32_IRQ_INTERRUPTS+2) /* 2: Tamper and time stamp interrupts */
+#define STM32_IRQ_RTC_WKUP (STM32_IRQ_INTERRUPTS+3) /* 3: RTC global interrupt */
+#define STM32_IRQ_FLASH (STM32_IRQ_INTERRUPTS+4) /* 4: Flash global interrupt */
+#define STM32_IRQ_RCC (STM32_IRQ_INTERRUPTS+5) /* 5: RCC global interrupt */
+#define STM32_IRQ_EXTI0 (STM32_IRQ_INTERRUPTS+6) /* 6: EXTI Line 0 interrupt */
+#define STM32_IRQ_EXTI1 (STM32_IRQ_INTERRUPTS+7) /* 7: EXTI Line 1 interrupt */
+#define STM32_IRQ_EXTI2 (STM32_IRQ_INTERRUPTS+8) /* 8: EXTI Line 2 interrupt */
+#define STM32_IRQ_EXTI3 (STM32_IRQ_INTERRUPTS+9) /* 9: EXTI Line 3 interrupt */
+#define STM32_IRQ_EXTI4 (STM32_IRQ_INTERRUPTS+10) /* 10: EXTI Line 4 interrupt */
+#define STM32_IRQ_DMA1S0 (STM32_IRQ_INTERRUPTS+11) /* 11: DMA1 Stream 0 global interrupt */
+#define STM32_IRQ_DMA1S1 (STM32_IRQ_INTERRUPTS+12) /* 12: DMA1 Stream 1 global interrupt */
+#define STM32_IRQ_DMA1S2 (STM32_IRQ_INTERRUPTS+13) /* 13: DMA1 Stream 2 global interrupt */
+#define STM32_IRQ_DMA1S3 (STM32_IRQ_INTERRUPTS+14) /* 14: DMA1 Stream 3 global interrupt */
+#define STM32_IRQ_DMA1S4 (STM32_IRQ_INTERRUPTS+15) /* 15: DMA1 Stream 4 global interrupt */
+#define STM32_IRQ_DMA1S5 (STM32_IRQ_INTERRUPTS+16) /* 16: DMA1 Stream 5 global interrupt */
+#define STM32_IRQ_DMA1S6 (STM32_IRQ_INTERRUPTS+17) /* 17: DMA1 Stream 6 global interrupt */
+#define STM32_IRQ_ADC (STM32_IRQ_INTERRUPTS+18) /* 18: ADC1, ADC2, and ADC3 global interrupt */
+#define STM32_IRQ_CAN1TX (STM32_IRQ_INTERRUPTS+19) /* 19: CAN1 TX interrupts */
+#define STM32_IRQ_CAN1RX0 (STM32_IRQ_INTERRUPTS+20) /* 20: CAN1 RX0 interrupts */
+#define STM32_IRQ_CAN1RX1 (STM32_IRQ_INTERRUPTS+21) /* 21: CAN1 RX1 interrupt */
+#define STM32_IRQ_CAN1SCE (STM32_IRQ_INTERRUPTS+22) /* 22: CAN1 SCE interrupt */
+#define STM32_IRQ_EXTI95 (STM32_IRQ_INTERRUPTS+23) /* 23: EXTI Line[9:5] interrupts */
+#define STM32_IRQ_TIM1BRK (STM32_IRQ_INTERRUPTS+24) /* 24: TIM1 Break interrupt */
+#define STM32_IRQ_TIM9 (STM32_IRQ_INTERRUPTS+24) /* 24: TIM9 global interrupt */
+#define STM32_IRQ_TIM1UP (STM32_IRQ_INTERRUPTS+25) /* 25: TIM1 Update interrupt */
+#define STM32_IRQ_TIM10 (STM32_IRQ_INTERRUPTS+25) /* 25: TIM10 global interrupt */
+#define STM32_IRQ_TIM1TRGCOM (STM32_IRQ_INTERRUPTS+26) /* 26: TIM1 Trigger and Commutation interrupts */
+#define STM32_IRQ_TIM11 (STM32_IRQ_INTERRUPTS+26) /* 26: TIM11 global interrupt */
+#define STM32_IRQ_TIM1CC (STM32_IRQ_INTERRUPTS+27) /* 27: TIM1 Capture Compare interrupt */
+#define STM32_IRQ_TIM2 (STM32_IRQ_INTERRUPTS+28) /* 28: TIM2 global interrupt */
+#define STM32_IRQ_TIM3 (STM32_IRQ_INTERRUPTS+29) /* 29: TIM3 global interrupt */
+#define STM32_IRQ_TIM4 (STM32_IRQ_INTERRUPTS+30) /* 30: TIM4 global interrupt */
+#define STM32_IRQ_I2C1EV (STM32_IRQ_INTERRUPTS+31) /* 31: I2C1 event interrupt */
+#define STM32_IRQ_I2C1ER (STM32_IRQ_INTERRUPTS+32) /* 32: I2C1 error interrupt */
+#define STM32_IRQ_I2C2EV (STM32_IRQ_INTERRUPTS+33) /* 33: I2C2 event interrupt */
+#define STM32_IRQ_I2C2ER (STM32_IRQ_INTERRUPTS+34) /* 34: I2C2 error interrupt */
+#define STM32_IRQ_SPI1 (STM32_IRQ_INTERRUPTS+35) /* 35: SPI1 global interrupt */
+#define STM32_IRQ_SPI2 (STM32_IRQ_INTERRUPTS+36) /* 36: SPI2 global interrupt */
+#define STM32_IRQ_USART1 (STM32_IRQ_INTERRUPTS+37) /* 37: USART1 global interrupt */
+#define STM32_IRQ_USART2 (STM32_IRQ_INTERRUPTS+38) /* 38: USART2 global interrupt */
+#define STM32_IRQ_USART3 (STM32_IRQ_INTERRUPTS+39) /* 39: USART3 global interrupt */
+#define STM32_IRQ_EXTI1510 (STM32_IRQ_INTERRUPTS+40) /* 40: EXTI Line[15:10] interrupts */
+#define STM32_IRQ_RTCALRM (STM32_IRQ_INTERRUPTS+41) /* 41: RTC alarm through EXTI line interrupt */
+#define STM32_IRQ_OTGFSWKUP (STM32_IRQ_INTERRUPTS+42) /* 42: USB On-The-Go FS Wakeup through EXTI line interrupt */
+#define STM32_IRQ_TIM8BRK (STM32_IRQ_INTERRUPTS+43) /* 43: TIM8 Break interrupt */
+#define STM32_IRQ_TIM12 (STM32_IRQ_INTERRUPTS+43) /* 43: TIM12 global interrupt */
+#define STM32_IRQ_TIM8UP (STM32_IRQ_INTERRUPTS+44) /* 44: TIM8 Update interrupt */
+#define STM32_IRQ_TIM13 (STM32_IRQ_INTERRUPTS+44) /* 44: TIM13 global interrupt */
+#define STM32_IRQ_TIM8TRGCOM (STM32_IRQ_INTERRUPTS+45) /* 45: TIM8 Trigger and Commutation interrupts */
+#define STM32_IRQ_TIM14 (STM32_IRQ_INTERRUPTS+45) /* 45: TIM14 global interrupt */
+#define STM32_IRQ_TIM8CC (STM32_IRQ_INTERRUPTS+46) /* 46: TIM8 Capture Compare interrupt */
+#define STM32_IRQ_DMA1S7 (STM32_IRQ_INTERRUPTS+47) /* 47: DMA1 Stream 7 global interrupt */
+#define STM32_IRQ_FSMC (STM32_IRQ_INTERRUPTS+48) /* 48: FSMC global interrupt */
+#define STM32_IRQ_SDIO (STM32_IRQ_INTERRUPTS+49) /* 49: SDIO global interrupt */
+#define STM32_IRQ_TIM5 (STM32_IRQ_INTERRUPTS+50) /* 50: TIM5 global interrupt */
+#define STM32_IRQ_SPI3 (STM32_IRQ_INTERRUPTS+51) /* 51: SPI3 global interrupt */
+#define STM32_IRQ_UART4 (STM32_IRQ_INTERRUPTS+52) /* 52: UART4 global interrupt */
+#define STM32_IRQ_UART5 (STM32_IRQ_INTERRUPTS+53) /* 53: UART5 global interrupt */
+#define STM32_IRQ_TIM6 (STM32_IRQ_INTERRUPTS+54) /* 54: TIM6 global interrupt */
+#define STM32_IRQ_DAC (STM32_IRQ_INTERRUPTS+54) /* 54: DAC1 and DAC2 underrun error interrupts */
+#define STM32_IRQ_TIM7 (STM32_IRQ_INTERRUPTS+55) /* 55: TIM7 global interrupt */
+#define STM32_IRQ_DMA2S0 (STM32_IRQ_INTERRUPTS+56) /* 56: DMA2 Stream 0 global interrupt */
+#define STM32_IRQ_DMA2S1 (STM32_IRQ_INTERRUPTS+57) /* 57: DMA2 Stream 1 global interrupt */
+#define STM32_IRQ_DMA2S2 (STM32_IRQ_INTERRUPTS+58) /* 58: DMA2 Stream 2 global interrupt */
+#define STM32_IRQ_DMA2S3 (STM32_IRQ_INTERRUPTS+59) /* 59: DMA2 Stream 3 global interrupt */
+#define STM32_IRQ_DMA2S4 (STM32_IRQ_INTERRUPTS+60) /* 60: DMA2 Stream 4 global interrupt */
+#define STM32_IRQ_ETH (STM32_IRQ_INTERRUPTS+61) /* 61: Ethernet global interrupt */
+#define STM32_IRQ_ETHWKUP (STM32_IRQ_INTERRUPTS+62) /* 62: Ethernet Wakeup through EXTI line interrupt */
+#define STM32_IRQ_CAN2TX (STM32_IRQ_INTERRUPTS+63) /* 63: CAN2 TX interrupts */
+#define STM32_IRQ_CAN2RX0 (STM32_IRQ_INTERRUPTS+64) /* 64: CAN2 RX0 interrupts */
+#define STM32_IRQ_CAN2RX1 (STM32_IRQ_INTERRUPTS+65) /* 65: CAN2 RX1 interrupt */
+#define STM32_IRQ_CAN2SCE (STM32_IRQ_INTERRUPTS+66) /* 66: CAN2 SCE interrupt */
+#define STM32_IRQ_OTGFS (STM32_IRQ_INTERRUPTS+67) /* 67: USB On The Go FS global interrupt */
+#define STM32_IRQ_DMA2S5 (STM32_IRQ_INTERRUPTS+68) /* 68: DMA2 Stream 5 global interrupt */
+#define STM32_IRQ_DMA2S6 (STM32_IRQ_INTERRUPTS+69) /* 69: DMA2 Stream 6 global interrupt */
+#define STM32_IRQ_DMA2S7 (STM32_IRQ_INTERRUPTS+70) /* 70: DMA2 Stream 7 global interrupt */
+#define STM32_IRQ_USART6 (STM32_IRQ_INTERRUPTS+71) /* 71: USART6 global interrupt */
+#define STM32_IRQ_I2C3EV (STM32_IRQ_INTERRUPTS+72) /* 72: I2C3 event interrupt */
+#define STM32_IRQ_I2C3ER (STM32_IRQ_INTERRUPTS+73) /* 73: I2C3 error interrupt */
+#define STM32_IRQ_OTGHSEP1OUT (STM32_IRQ_INTERRUPTS+74) /* 74: USB On The Go HS End Point 1 Out global interrupt */
+#define STM32_IRQ_OTGHSEP1IN (STM32_IRQ_INTERRUPTS+75) /* 75: USB On The Go HS End Point 1 In global interrupt */
+#define STM32_IRQ_OTGHSWKUP (STM32_IRQ_INTERRUPTS+76) /* 76: USB On The Go HS Wakeup through EXTI interrupt */
+#define STM32_IRQ_OTGHS (STM32_IRQ_INTERRUPTS+77) /* 77: USB On The Go HS global interrupt */
+#define STM32_IRQ_DCMI (STM32_IRQ_INTERRUPTS+78) /* 78: DCMI global interrupt */
+#define STM32_IRQ_CRYP (STM32_IRQ_INTERRUPTS+79) /* 79: CRYP crypto global interrupt */
+#define STM32_IRQ_HASH (STM32_IRQ_INTERRUPTS+80) /* 80: Hash and Rng global interrupt */
+#define STM32_IRQ_RNG (STM32_IRQ_INTERRUPTS+80) /* 80: Hash and Rng global interrupt */
+#define STM32_IRQ_FPU (STM32_IRQ_INTERRUPTS+81) /* 81: FPU global interrupt */
+
+#define NR_IRQS (STM32_IRQ_INTERRUPTS+82)
+
+/****************************************************************************************************
+ * Public Types
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Public Data
+ ****************************************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************************************
+ * Public Functions
+ ****************************************************************************************************/
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_STM32F40XXX_IRQ_H */
+
diff --git a/nuttx/arch/arm/include/syscall.h b/nuttx/arch/arm/include/syscall.h
new file mode 100644
index 000000000..4c9eee63e
--- /dev/null
+++ b/nuttx/arch/arm/include/syscall.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * arch/arm/include/syscall.h
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directed but, rather, only indirectly
+ * through include/syscall.h or include/sys/sycall.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_SYSCALL_H
+#define __ARCH_ARM_INCLUDE_SYSCALL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/* Include ARM architecture-specific syscall macros */
+
+#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4)
+# include <arch/armv7-m/syscall.h>
+#else
+# include <arch/arm/syscall.h>
+#endif
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif /* __ARCH_ARM_INCLUDE_SYSCALL_H */
+
diff --git a/nuttx/arch/arm/include/types.h b/nuttx/arch/arm/include/types.h
new file mode 100644
index 000000000..c3471ca59
--- /dev/null
+++ b/nuttx/arch/arm/include/types.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+ * arch/arm/include/types.h
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/* This file should never be included directed but, rather, only indirectly
+ * through sys/types.h
+ */
+
+#ifndef __ARCH_ARM_INCLUDE_TYPES_H
+#define __ARCH_ARM_INCLUDE_TYPES_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Type Declarations
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/* These are the sizes of the standard integer types. NOTE that these type
+ * names have a leading underscore character. This file will be included
+ * (indirectly) by include/stdint.h and typedef'ed to the final name without
+ * the underscore character. This roundabout way of doings things allows
+ * the stdint.h to be removed from the include/ directory in the event that
+ * the user prefers to use the definitions provided by their toolchain header
+ * files
+ */
+
+typedef signed char _int8_t;
+typedef unsigned char _uint8_t;
+
+typedef signed short _int16_t;
+typedef unsigned short _uint16_t;
+
+typedef signed int _int32_t;
+typedef unsigned int _uint32_t;
+
+typedef signed long long _int64_t;
+typedef unsigned long long _uint64_t;
+#define __INT64_DEFINED
+
+/* A pointer is 4 bytes */
+
+typedef signed int _intptr_t;
+typedef unsigned int _uintptr_t;
+
+/* This is the size of the interrupt state save returned by irqsave(). For
+ * ARM, a 32 register value is returned, for the thumb2, Cortex-M3, the 16-bit
+ * primask register value is returned,
+ */
+
+#ifdef __thumb2__
+typedef unsigned short irqstate_t;
+#else /* __thumb2__ */
+typedef unsigned int irqstate_t;
+#endif /* __thumb2__ */
+
+#endif /* __ASSEMBLY__ */
+
+/****************************************************************************
+ * Global Function Prototypes
+ ****************************************************************************/
+
+#endif /* __ARCH_ARM_INCLUDE_TYPES_H */
diff --git a/nuttx/arch/arm/include/watchdog.h b/nuttx/arch/arm/include/watchdog.h
new file mode 100644
index 000000000..f70b8d2e9
--- /dev/null
+++ b/nuttx/arch/arm/include/watchdog.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+ * arch/arm/include/watchdog.h
+ *
+ * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_INCLUDE_WATCHDOG_H
+#define __ARCH_ARM_INCLUDE_WATCHDOG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/fs/ioctl.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#endif /* __ARCH_ARM_INCLUDE_WATCHDOG_H */
diff --git a/nuttx/arch/arm/src/Makefile b/nuttx/arch/arm/src/Makefile
new file mode 100644
index 000000000..ef0415375
--- /dev/null
+++ b/nuttx/arch/arm/src/Makefile
@@ -0,0 +1,162 @@
+############################################################################
+# arch/arm/src/Makefile
+#
+# Copyright (C) 2007-2009, 2011-2012 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.
+#
+############################################################################
+
+-include $(TOPDIR)/Make.defs
+-include chip/Make.defs
+
+ARCH_SRCDIR = $(TOPDIR)/arch/$(CONFIG_ARCH)/src
+ifeq ($(CONFIG_ARCH_CORTEXM3),y) # Cortex-M3 is ARMv7-M
+ARCH_SUBDIR = armv7-m
+else
+ifeq ($(CONFIG_ARCH_CORTEXM4),y) # Cortex-M4 is ARMv7E-M
+ARCH_SUBDIR = armv7-m
+else
+ARCH_SUBDIR = arm
+endif
+endif
+
+ifeq ($(WINTOOL),y)
+ NUTTX = "${shell cygpath -w $(TOPDIR)/nuttx}"
+ CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/chip}" \
+ -I "${shell cygpath -w $(ARCH_SRCDIR)/common}" \
+ -I "${shell cygpath -w $(ARCH_SRCDIR)/$(ARCH_SUBDIR)}" \
+ -I "${shell cygpath -w $(TOPDIR)/sched}"
+else
+ NUTTX = $(TOPDIR)/nuttx
+ CFLAGS += -I$(ARCH_SRCDIR)/chip -I$(ARCH_SRCDIR)/common \
+ -I$(ARCH_SRCDIR)/$(ARCH_SUBDIR) -I$(TOPDIR)/sched
+endif
+
+HEAD_OBJ = $(HEAD_ASRC:.S=$(OBJEXT))
+
+ASRCS = $(CHIP_ASRCS) $(CMN_ASRCS)
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+
+CSRCS = $(CHIP_CSRCS) $(CMN_CSRCS)
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+LDFLAGS = $(ARCHSCRIPT)
+EXTRA_LIBS ?=
+
+LINKLIBS =
+ifeq ($(WINTOOL),y)
+ LIBPATHS = ${shell for path in $(LINKLIBS); do dir=`dirname $(TOPDIR)/$$path`;echo "-L\"`cygpath -w $$dir`\"";done}
+ LIBPATHS += -L"${shell cygpath -w $(BOARDDIR)}"
+else
+ LIBPATHS = $(addprefix -L$(TOPDIR)/,$(dir $(LINKLIBS)))
+ LIBPATHS += -L"$(BOARDDIR)"
+endif
+LDLIBS = $(patsubst lib%,-l%,$(basename $(notdir $(LINKLIBS))))
+
+BOARDDIR = $(TOPDIR)/arch/$(CONFIG_ARCH)/src/board
+
+LIBGCC = "${shell $(CC) $(ARCHCPUFLAGS) -print-libgcc-file-name}"
+
+VPATH = chip:common:$(ARCH_SUBDIR)
+
+all: $(HEAD_OBJ) libarch$(LIBEXT)
+
+.PHONY: board/libboard$(LIBEXT)
+
+$(AOBJS) $(HEAD_OBJ): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+libarch$(LIBEXT): $(OBJS)
+ @( for obj in $(OBJS) ; do \
+ $(call ARCHIVE, $@, $${obj}); \
+ done ; )
+
+board/libboard$(LIBEXT):
+ @$(MAKE) -C board TOPDIR="$(TOPDIR)" libboard$(LIBEXT) EXTRADEFINES=$(EXTRADEFINES)
+
+nuttx: $(HEAD_OBJ) board/libboard$(LIBEXT)
+ @echo "LD: nuttx"
+ @$(LD) --entry=__start $(LDFLAGS) $(LIBPATHS) -o $(NUTTX)$(EXEEXT) $(HEAD_OBJ) $(EXTRA_OBJS) \
+ --start-group $(LDLIBS) -lboard $(EXTRA_LIBS) $(LIBGCC) --end-group
+ifeq ($(CONFIG_BOOT_RUNFROMFLASH),y)
+ @export flashloc=`$(OBJDUMP) --all-headers $(NUTTX)$(EXEEXT) | grep _eronly | cut -d' ' -f1`; \
+ $(OBJCOPY) $(OBJCOPYARGS) --adjust-section-vma=.data=0x$$flashloc $(NUTTX)$(EXEEXT) $(NUTTX).flashimage
+ @mv $(NUTTX).flashimage $(NUTTX)$(EXEEXT)
+endif
+ @$(NM) $(NUTTX)$(EXEEXT) | \
+ grep -v '\(compiled\)\|\(\$(OBJEXT)$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \
+ sort > $(TOPDIR)/System.map
+
+# This is part of the top-level export target
+# Note that there may not be a head object if layout is handled
+# by the linker configuration.
+
+export_head: board/libboard$(LIBEXT) $(HEAD_OBJ)
+ifneq ($(HEAD_OBJ),)
+ @if [ -d "$(EXPORT_DIR)/startup" ]; then \
+ cp -f $(HEAD_OBJ) "$(EXPORT_DIR)/startup"; \
+ else \
+ echo "$(EXPORT_DIR)/startup does not exist"; \
+ exit 1; \
+ fi
+endif
+
+# Dependencies
+
+.depend: Makefile chip/Make.defs $(SRCS)
+ @if [ -e board/Makefile ]; then \
+ $(MAKE) -C board TOPDIR="$(TOPDIR)" depend ; \
+ fi
+ @$(MKDEP) --dep-path chip --dep-path common --dep-path $(ARCH_SUBDIR) \
+ $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+depend: .depend
+
+clean:
+ @if [ -e board/Makefile ]; then \
+ $(MAKE) -C board TOPDIR="$(TOPDIR)" clean ; \
+ fi
+ @rm -f libarch$(LIBEXT) *~ .*.swp
+ $(call CLEAN)
+
+distclean: clean
+ @if [ -e board/Makefile ]; then \
+ $(MAKE) -C board TOPDIR="$(TOPDIR)" distclean ; \
+ fi
+ @rm -f Make.dep .depend
+
+-include Make.dep
diff --git a/nuttx/arch/arm/src/arm/arm.h b/nuttx/arch/arm/src/arm/arm.h
new file mode 100644
index 000000000..433283814
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/arm.h
@@ -0,0 +1,451 @@
+/************************************************************************************
+ * arch/arm/src/arm/arm.h
+ *
+ * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_COMMON_ARM_H
+#define __ARCH_ARM_SRC_COMMON_ARM_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#undef CONFIG_ALIGNMENT_TRAP
+#undef CONFIG_DCACHE_WRITETHROUGH
+#undef CONFIG_CACHE_ROUND_ROBIN
+#undef CONFIG_DCACHE_DISABLE
+#undef CONFIG_ICACHE_DISABLE
+
+/* ARM9EJS **************************************************************************/
+
+/* PSR bits */
+
+#define MODE_MASK 0x0000001f /* Bits 0-4: Mode bits */
+# define USR26_MODE 0x00000000 /* 26-bit User mode */
+# define FIQ26_MODE 0x00000001 /* 26-bit FIQ mode */
+# define IRQ26_MODE 0x00000002 /* 26-bit IRQ mode */
+# define SVC26_MODE 0x00000003 /* 26-bit Supervisor mode */
+# define MODE32_BIT 0x00000010 /* Bit 4: 32-bit mode */
+# define USR_MODE 0x00000010 /* 32-bit User mode */
+# define FIQ_MODE 0x00000011 /* 32-bit FIQ mode */
+# define IRQ_MODE 0x00000012 /* 32-bit IRQ mode */
+# define SVC_MODE 0x00000013 /* 32-bit Supervisor mode */
+# define ABT_MODE 0x00000017 /* 32-bit Abort mode */
+# define UND_MODE 0x0000001b /* 32-bit Undefined mode */
+# define SYSTEM_MODE 0x0000001f /* 32-bit System mode */
+#define PSR_T_BIT 0x00000020 /* Bit 5: Thumb state */
+#define PSR_F_BIT 0x00000040 /* Bit 6: FIQ disable */
+#define PSR_I_BIT 0x00000080 /* Bit 7: IRQ disable */
+ /* Bits 8-23: Reserved */
+#define PSR_J_BIT 0x01000000 /* Bit 24: Jazelle state bit */
+ /* Bits 25-26: Reserved */
+#define PSR_Q_BIT 0x08000000 /* Bit 27: Sticky overflow */
+#define PSR_V_BIT 0x10000000 /* Bit 28: Overflow */
+#define PSR_C_BIT 0x20000000 /* Bit 29: Carry/Borrow/Extend */
+#define PSR_Z_BIT 0x40000000 /* Bit 30: Zero */
+#define PSR_N_BIT 0x80000000 /* Bit 31: Negative/Less than */
+
+/* CR1 bits (CP#15 CR1) */
+
+#define CR_M 0x00000001 /* MMU enable */
+#define CR_A 0x00000002 /* Alignment abort enable */
+#define CR_C 0x00000004 /* Dcache enable */
+#define CR_W 0x00000008 /* Write buffer enable */
+#define CR_P 0x00000010 /* 32-bit exception handler */
+#define CR_D 0x00000020 /* 32-bit data address range */
+#define CR_L 0x00000040 /* Implementation defined */
+#define CR_B 0x00000080 /* Big endian */
+#define CR_S 0x00000100 /* System MMU protection */
+#define CR_R 0x00000200 /* ROM MMU protection */
+#define CR_F 0x00000400 /* Implementation defined */
+#define CR_Z 0x00000800 /* Implementation defined */
+#define CR_I 0x00001000 /* Icache enable */
+#define CR_V 0x00002000 /* Vectors relocated to 0xffff0000 */
+#define CR_RR 0x00004000 /* Round Robin cache replacement */
+#define CR_L4 0x00008000 /* LDR pc can set T bit */
+#define CR_DT 0x00010000
+#define CR_IT 0x00040000
+#define CR_ST 0x00080000
+#define CR_FI 0x00200000 /* Fast interrupt (lower latency mode) */
+#define CR_U 0x00400000 /* Unaligned access operation */
+#define CR_XP 0x00800000 /* Extended page tables */
+#define CR_VE 0x01000000 /* Vectored interrupts */
+
+/* The lowest 4-bits of the FSR register indicates the fault generated by
+ * the MMU.
+ */
+
+#define FSR_MASK 15 /* Bits 0-3: Type of fault */
+#define FSR_VECTOR 0 /* Vector exception */
+#define FSR_ALIGN1 1 /* Alignment fault */
+#define FSR_TERMINAL 2 /* Terminal exception */
+#define FSR_ALIGN2 3 /* Alignment fault */
+#define FSR_LINESECT 4 /* External abort on linefetch for section translation */
+#define FSR_SECT 5 /* Section translation fault (unmapped virtual address) */
+#define FSR_LINEPAGE 6 /* External abort on linefetch for page translation */
+#define FSR_PAGE 7 /* Page translation fault (unmapped virtual address) */
+#define FSR_NLINESECT 8 /* External abort on non-linefetch for section translation */
+#define FSR_DOMSECT 9 /* Domain fault on section translation (i.e. accessing invalid domain) */
+#define FSR_NLINEPAGE 10 /* External abort on non-linefetch for page translation */
+#define FSR_DOMPAGE 11 /* Domain fault on page translation (i.e. accessing invalid domain) */
+#define FSR_EXTERN1 12 /* External abort on first level translation */
+#define FSR_PERMSECT 13 /* Permission fault on section (i.e. no permission to access virtual address) */
+#define FSR_EXTERN2 14 /* External abort on second level translation */
+#define FSR_PERMPAGE 15 /* Permission fault on page (i.e. no permission to access virtual address) */
+
+#define FSR_DOM_SHIFT 4 /* Bits 4-7: Domain */
+#define FSR_DOM_MASK (15 << FSR_DOM_SHIFT)
+
+/* Hardware page table definitions.
+ *
+ * Level 1 Descriptor (PMD)
+ *
+ * Common definitions.
+ */
+
+#define PMD_TYPE_MASK 0x00000003 /* Bits 1:0: Type of descriptor */
+#define PMD_TYPE_FAULT 0x00000000
+#define PMD_TYPE_COARSE 0x00000001
+#define PMD_TYPE_SECT 0x00000002
+#define PMD_TYPE_FINE 0x00000003
+ /* Bits 3:2: Depends on descriptor */
+#define PMD_BIT4 0x00000010 /* Bit 4: Must be one */
+#define PMD_DOMAIN_MASK 0x000001e0 /* Bits 8:5: Domain control bits */
+#define PMD_DOMAIN(x) ((x) << 5)
+#define PMD_PROTECTION 0x00000200 /* Bit 9: v5 only */
+ /* Bits 31:10: Depend on descriptor */
+
+/* Level 1 Section Descriptor. Section descriptors allow fast, single
+ * level mapping between 1Mb address regions.
+ */
+ /* Bits 1:0: Type of mapping */
+#define PMD_SECT_BUFFERABLE 0x00000004 /* Bit 2: 1=bufferable */
+#define PMD_SECT_CACHEABLE 0x00000008 /* Bit 3: 1=cacheable */
+ /* Bit 4: Common, must be one */
+ /* Bits 8:5: Common domain control */
+ /* Bit 9: Common protection */
+#define PMD_SECT_AP_MASK 0x00000c00 /* Bits 11:10: Access permission */
+#define PMD_SECT_AP_WRITE 0x00000400
+#define PMD_SECT_AP_READ 0x00000800
+ /* Bits 19:20: Should be zero */
+#define PMD_SECT_TEX_MASK 0xfff00000 /* Bits 31:20: v5, Physical page */
+#define PMD_SECT_APX 0x00008000 /* Bit 15: v6 only */
+#define PMD_SECT_S 0x00010000 /* Bit 16: v6 only */
+#define PMD_SECT_nG 0x00020000 /* Bit 17: v6 only */
+
+#define PMD_SECT_UNCACHED (0)
+#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE)
+#define PMD_SECT_WT (PMD_SECT_CACHEABLE)
+#define PMD_SECT_WB (PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE)
+#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1)|PMD_SECT_CACHEABLE)
+#define PMD_SECT_WBWA (PMD_SECT_TEX(1)|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE)
+
+/* Level 1 Coarse Table Descriptor. Coarse Table Descriptors support
+ * two level mapping between 16Kb memory regions.
+ */
+ /* Bits 1:0: Type of mapping */
+ /* Bits 3:2: Should be zero */
+ /* Bit 4: Common, must be one */
+ /* Bits 8:5: Common domain control */
+ /* Bits 9: Should be zero */
+#define PMD_COARSE_TEX_MASK 0xfffffc00 /* Bits 31:10: v5, Physical page */
+
+/* Level 1 Fine Table Descriptor. Coarse Table Descriptors support
+ * two level mapping between 4Kb memory regions.
+ */
+
+ /* Bits 1:0: Type of mapping */
+ /* Bits 3:2: Should be zero */
+ /* Bit 4: Common, must be one */
+ /* Bits 8:5: Common domain control */
+ /* Bits 11:9: Should be zero */
+#define PMD_FINE_TEX_MASK 0xfffff000 /* Bits 31:12: v5, Physical page */
+
+/* Level 2 Table Descriptor (PTE). A section descriptor provides the base address
+ * of a 1MB block of memory. The page table descriptors provide the base address of
+ * a page table that contains second-level descriptors. There are two sizes of page
+ * table:
+ * - Coarse page tables have 256 entries, splitting the 1MB that the table
+ * describes into 4KB blocks
+ * - Fine/tiny page tables have 1024 entries, splitting the 1MB that the table
+ * describes into 1KB blocks.
+ *
+ * The following definitions apply to all L2 tables:
+ */
+
+#define PTE_TYPE_MASK (3 << 0) /* Bits: 1:0: Type of mapping */
+#define PTE_TYPE_FAULT (0 << 0) /* None */
+#define PTE_TYPE_LARGE (1 << 0) /* 64Kb of memory */
+#define PTE_TYPE_SMALL (2 << 0) /* 4Kb of memory */
+#define PTE_TYPE_TINY (3 << 0) /* 1Kb of memory (v5)*/
+#define PTE_BUFFERABLE (1 << 2) /* Bit 2: 1=bufferable */
+#define PTE_CACHEABLE (1 << 3) /* Bit 3: 1=cacheable */
+ /* Bits 31:4: Depend on type */
+
+/* Large page -- 64Kb */
+ /* Bits: 1:0: Type of mapping */
+ /* Bits: 3:2: Bufferable/cacheable */
+#define PTE_LARGE_AP_MASK (0xff << 4) /* Bits 11:4 Access permissions */
+#define PTE_LARGE_AP_UNO_SRO (0x00 << 4)
+#define PTE_LARGE_AP_UNO_SRW (0x55 << 4)
+#define PTE_LARGE_AP_URO_SRW (0xaa << 4)
+#define PTE_LARGE_AP_URW_SRW (0xff << 4)
+ /* Bits 15:12: Should be zero */
+#define PTE_LARGE_TEX_MASK 0xffff0000 /* Bits 31:16: v5, Physical page */
+
+/* Small page -- 4Kb */
+
+ /* Bits: 1:0: Type of mapping */
+ /* Bits: 3:2: Bufferable/cacheable */
+#define PTE_SMALL_AP_MASK (0xff << 4) /* Bits: 11:4: Access permissions */
+#define PTE_SMALL_AP_UNO_SRO (0x00 << 4)
+#define PTE_SMALL_AP_UNO_SRW (0x55 << 4)
+#define PTE_SMALL_AP_URO_SRW (0xaa << 4)
+#define PTE_SMALL_AP_URW_SRW (0xff << 4)
+#define PTE_SMALL_TEX_MASK 0xfffff000 /* Bits: 31:12: Physical page */
+
+#define PTE_SMALL_NPAGES 256 /* 256 Coarse PTE's per section */
+
+/* Fine/Tiny page -- 1Kb */
+
+ /* Bits: 1:0: Type of mapping */
+ /* Bits: 3:2: Bufferable/cacheable */
+#define PTE_EXT_AP_MASK (3 << 4) /* Bits: 5:4: Access persions */
+#define PTE_EXT_AP_UNO_SRO (0 << 4)
+#define PTE_EXT_AP_UNO_SRW (1 << 4)
+#define PTE_EXT_AP_URO_SRW (2 << 4)
+#define PTE_EXT_AP_URW_SRW (3 << 4)
+ /* Bits: 9:6: Should be zero */
+#define PTE_TINY_TEX_MASK 0xfffffc00 /* Bits: 31:10: Physical page */
+
+#define PTE_TINY_NPAGES 1024 /* 1024 Tiny PTE's per section */
+
+/* Default MMU flags for RAM memory, IO, vector region */
+
+#define MMU_ROMFLAGS \
+ (PMD_TYPE_SECT|PMD_BIT4|PMD_SECT_AP_READ)
+
+#define MMU_MEMFLAGS \
+ (PMD_TYPE_SECT|PMD_SECT_WB|PMD_BIT4|PMD_SECT_AP_WRITE|PMD_SECT_AP_READ)
+
+#define MMU_IOFLAGS \
+ (PMD_TYPE_SECT|PMD_BIT4|PMD_SECT_AP_WRITE|PMD_SECT_AP_READ)
+
+#define MMU_L1_VECTORFLAGS (PMD_TYPE_COARSE|PMD_BIT4)
+#define MMU_L2_VECTORFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW)
+
+/* Mapped section size */
+
+#define SECTION_SIZE (1 << 20) /* 1Mb */
+
+/* CP15 register c2 contains a pointer to the base address of a paged table in
+ * physical memory. Only bits 14-31 of the page table address is retained there;
+ * The full 30-bit address is formed by ORing in bits 2-13 or the virtual address
+ * (MVA). As a consequence, the page table must be aligned to a 16Kb address in
+ * physical memory and could require up to 16Kb of memory.
+ */
+
+#define PGTABLE_SIZE 0x00004000
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/* Get the current value of the CP15 C1 control register */
+
+static inline unsigned int get_cp15c1(void)
+{
+ unsigned int retval;
+ __asm__ __volatile__
+ (
+ "\tmrc p15, 0, %0, c1, c0"
+ : "=r" (retval)
+ :
+ : "memory");
+ return retval;
+}
+
+/* Get the current value of the CP15 C2 page table pointer register */
+
+static inline unsigned int get_cp15c2(void)
+{
+ unsigned int retval;
+ __asm__ __volatile__
+ (
+ "\tmrc p15, 0, %0, c2, c0"
+ : "=r" (retval)
+ :
+ : "memory");
+ return retval;
+}
+/* Get the current value of the CP15 C3 domain access register */
+
+static inline unsigned int get_cp15c3(void)
+{
+ unsigned int retval;
+ __asm__ __volatile__
+ (
+ "\tmrc p15, 0, %0, c3, c0"
+ : "=r" (retval)
+ :
+ : "memory");
+ return retval;
+}
+
+/* ARMv4/ARMv5 operation: Invalidate TLB
+ * ARM926EJ-S operation: Invalidate set-associative
+ * Data: Should be zero
+ */
+
+static inline void tlb_invalidate(void)
+{
+ unsigned int sbz = 0;
+ __asm__ __volatile__
+ (
+ "\tmcr p15, 0, %0, c8, c7, 0"
+ :
+ : "r" (sbz)
+ : "memory");
+}
+
+/* ARMv4/ARMv5 operation: Invalidate TLB single entry (MVA)
+ * ARM926EJ-S operation: Invalidate single entry
+ * Data: MVA
+ */
+
+static inline void tlb_invalidate_single(unsigned int mva)
+{
+ mva &= 0xfffffc00;
+ __asm__ __volatile__
+ (
+ "mcr p15, 0, %0, c8, c7, 1"
+ :
+ : "r" (mva)
+ : "memory");
+}
+
+/* ARMv4/ARMv5 operation: Invalidate instruction TLB
+ * ARM926EJ-S operation: Invalidate set-associative TLB
+ * Data: Should be zero
+ */
+
+static inline void tlb_instr_invalidate(void)
+{
+ unsigned int sbz = 0;
+ __asm__ __volatile__
+ (
+ "\tmcr p15, 0, %0, c8, c5, 0"
+ :
+ : "r" (sbz)
+ : "memory");
+}
+
+/* ARMv4/ARMv5 operation: Invalidate instruction TLB single entry (MVA)
+ * ARM926EJ-S operation: Invalidate single entry
+ * Data: MVA
+ */
+
+static inline void tlb_inst_invalidate_single(unsigned int mva)
+{
+ mva &= 0xfffffc00;
+ __asm__ __volatile__
+ (
+ "mcr p15, 0, %0, c8, c5, 1"
+ :
+ : "r" (mva)
+ : "memory");
+}
+
+/* ARMv4/ARMv5 operation: Invalidate data TLB
+ * ARM926EJ-S operation: Invalidate set-associative TLB
+ * Data: Should be zero
+ */
+
+static inline void tlb_data_invalidate(void)
+{
+ unsigned int sbz = 0;
+ __asm__ __volatile__
+ (
+ "\tmcr p15, 0, %0, c8, c6, 0"
+ :
+ : "r" (sbz)
+ : "memory");
+}
+
+/* ARMv4/ARMv5 operation: Invalidate data TLB single entry (MVA)
+ * ARM926EJ-S operation: Invalidate single entry
+ * Data: MVA
+ */
+
+static inline void tlb_data_invalidate_single(unsigned int mva)
+{
+ mva &= 0xfffffc00;
+ __asm__ __volatile__
+ (
+ "mcr p15, 0, %0, c8, c6, 1"
+ :
+ : "r" (mva)
+ : "memory");
+}
+
+#endif /* __ASSEMBLY__ */
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM_SRC_COMMON_ARM_H */
diff --git a/nuttx/arch/arm/src/arm/pg_macros.h b/nuttx/arch/arm/src/arm/pg_macros.h
new file mode 100644
index 000000000..fc50f6146
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/pg_macros.h
@@ -0,0 +1,522 @@
+/****************************************************************************
+ * arch/arm/src/arm/pg_macros.h
+ *
+ * Copyright (C) 2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/* Do not change this macro definition without making corresponding name
+ * changes in other files. This macro name is used in various places to
+ * assure that some file inclusion ordering dependencies are enforced.
+ */
+
+#ifndef __ARCH_ARM_SRC_ARM_PG_MACROS_H
+#define __ARCH_ARM_SRC_ARM_PG_MACROS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/page.h>
+
+#include "arm.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifdef CONFIG_PAGING
+
+/* Sanity check -- we cannot be using a ROM page table and supporting on-
+ * demand paging.
+ */
+
+#ifdef CONFIG_ARCH_ROMPGTABLE
+# error "Cannot support both CONFIG_PAGING and CONFIG_ARCH_ROMPGTABLE"
+#endif
+
+/* Virtual Page Table Location **********************************************/
+
+/* Check if the virtual address of the page table has been defined. It should
+ * not be defined: architecture specific logic should suppress defining
+ * PGTABLE_BASE_VADDR unless: (1) it is defined in the NuttX configuration
+ * file, or (2) the page table is position in low memory (because the vectors
+ * are in high memory).
+ */
+
+#ifndef PGTABLE_BASE_VADDR
+# define PGTABLE_BASE_VADDR (PG_LOCKED_VBASE + PG_TEXT_VSIZE + PG_DATA_SIZE)
+
+ /* Virtual base of the address of the L2 page tables need to recalculates
+ * using this new virtual base address of the L2 page table.
+ */
+
+# undef PGTABLE_L2_FINE_VBASE
+# define PGTABLE_L2_FINE_VBASE (PGTABLE_BASE_VADDR+PGTABLE_L2_FINE_OFFSET)
+
+# undef PGTABLE_L2_COARSE_VBASE
+# define PGTABLE_L2_COARSE_VBASE (PGTABLE_BASE_VADDR+PGTABLE_L2_COARSE_OFFSET)
+#endif
+
+/* Page Size Selections *****************************************************/
+
+/* Create some friendly definitions to handle some differences between
+ * small and tiny pages.
+ */
+
+#if CONFIG_PAGING_PAGESIZE == 1024
+
+ /* Base of the L2 page table (aligned to 4Kb byte boundaries) */
+
+# define PGTABLE_L2_BASE_PADDR PGTABLE_L2_FINE_PBASE
+# define PGTABLE_L2_BASE_VADDR PGTABLE_L2_FINE_VBASE
+
+ /* Number of pages in an L2 table per L1 entry */
+
+# define PTE_NPAGES PTE_TINY_NPAGES
+
+ /* Mask to get the page table physical address from an L1 entry */
+
+# define PG_L1_PADDRMASK PMD_FINE_TEX_MASK
+
+ /* MMU Flags for each memory region */
+
+# define MMU_L1_TEXTFLAGS (PMD_TYPE_FINE|PMD_BIT4)
+# define MMU_L2_TEXTFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRO|PTE_CACHEABLE)
+# define MMU_L1_DATAFLAGS (PMD_TYPE_FINE|PMD_BIT4)
+# define MMU_L2_DATAFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRW|PTE_CACHEABLE|PTE_BUFFERABLE)
+# define MMU_L2_ALLOCFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRW)
+# define MMU_L1_PGTABFLAGS (PMD_TYPE_FINE|PMD_BIT4)
+# define MMU_L2_PGTABFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRW)
+
+# define MMU_L2_VECTRWFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRW)
+# define MMU_L2_VECTROFLAGS (PTE_TYPE_TINY|PTE_EXT_AP_UNO_SRO|PTE_CACHEABLE)
+
+#elif CONFIG_PAGING_PAGESIZE == 4096
+
+ /* Base of the L2 page table (aligned to 1Kb byte boundaries) */
+
+# define PGTABLE_L2_BASE_PADDR PGTABLE_L2_COARSE_PBASE
+# define PGTABLE_L2_BASE_VADDR PGTABLE_L2_COARSE_VBASE
+
+ /* Number of pages in an L2 table per L1 entry */
+
+# define PTE_NPAGES PTE_SMALL_NPAGES
+
+ /* Mask to get the page table physical address from an L1 entry */
+
+# define PG_L1_PADDRMASK PMD_COARSE_TEX_MASK
+
+ /* MMU Flags for each memory region. */
+
+# define MMU_L1_TEXTFLAGS (PMD_TYPE_COARSE|PMD_BIT4)
+# define MMU_L2_TEXTFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRO|PTE_CACHEABLE)
+# define MMU_L1_DATAFLAGS (PMD_TYPE_COARSE|PMD_BIT4)
+# define MMU_L2_DATAFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW|PTE_CACHEABLE|PTE_BUFFERABLE)
+# define MMU_L2_ALLOCFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW)
+# define MMU_L1_PGTABFLAGS (PMD_TYPE_COARSE|PMD_BIT4)
+# define MMU_L2_PGTABFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW)
+
+# define MMU_L2_VECTRWFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRW)
+# define MMU_L2_VECTROFLAGS (PTE_TYPE_SMALL|PTE_SMALL_AP_UNO_SRO|PTE_CACHEABLE)
+
+#else
+# error "Need extended definitions for CONFIG_PAGING_PAGESIZE"
+#endif
+
+#define PT_SIZE (4*PTE_NPAGES)
+
+/* Addresses of Memory Regions **********************************************/
+
+/* We position the locked region PTEs at an offset into the first
+ * L2 page table. The L1 entry points to an 1Mb aligned virtual
+ * address. The actual L2 entry will be offset into the aligned
+ * L2 table.
+ *
+ * Coarse: PG_L1_PADDRMASK=0xfffffc00
+ * OFFSET=(((a) & 0x000fffff) >> 12) << 2)
+ * Fine: PG_L1_PADDRMASK=0xfffff000
+ * OFFSET=(((a) & 0x000fffff) >> 10) << 2)
+ */
+
+#define PG_L1_LOCKED_PADDR (PGTABLE_BASE_PADDR + ((PG_LOCKED_VBASE >> 20) << 2))
+#define PG_L1_LOCKED_VADDR (PGTABLE_BASE_VADDR + ((PG_LOCKED_VBASE >> 20) << 2))
+
+#define PG_L2_LOCKED_OFFSET (((PG_LOCKED_VBASE & 0x000fffff) >> PAGESHIFT) << 2)
+#define PG_L2_LOCKED_PADDR (PGTABLE_L2_BASE_PADDR + PG_L2_LOCKED_OFFSET)
+#define PG_L2_LOCKED_VADDR (PGTABLE_L2_BASE_VADDR + PG_L2_LOCKED_OFFSET)
+#define PG_L2_LOCKED_SIZE (4*CONFIG_PAGING_NLOCKED)
+
+/* We position the paged region PTEs immediately after the locked
+ * region PTEs. NOTE that the size of the paged regions is much
+ * larger than the size of the physical paged region. That is the
+ * core of what the On-Demanding Paging feature provides.
+ */
+
+#define PG_L1_PAGED_PADDR (PGTABLE_BASE_PADDR + ((PG_PAGED_VBASE >> 20) << 2))
+#define PG_L1_PAGED_VADDR (PGTABLE_BASE_VADDR + ((PG_PAGED_VBASE >> 20) << 2))
+
+#define PG_L2_PAGED_PADDR (PG_L2_LOCKED_PADDR + PG_L2_LOCKED_SIZE)
+#define PG_L2_PAGED_VADDR (PG_L2_LOCKED_VADDR + PG_L2_LOCKED_SIZE)
+#define PG_L2_PAGED_SIZE (4*CONFIG_PAGING_NVPAGED)
+
+/* This describes the overall text region */
+
+#define PG_L1_TEXT_PADDR PG_L1_LOCKED_PADDR
+#define PG_L1_TEXT_VADDR PG_L1_LOCKED_VADDR
+
+#define PG_L2_TEXT_PADDR PG_L2_LOCKED_PADDR
+#define PG_L2_TEXT_VADDR PG_L2_LOCKED_VADDR
+#define PG_L2_TEXT_SIZE (PG_L2_LOCKED_SIZE + PG_L2_PAGED_SIZE)
+
+/* We position the data section PTEs just after the text region PTE's */
+
+#define PG_L1_DATA_PADDR (PGTABLE_BASE_PADDR + ((PG_DATA_VBASE >> 20) << 2))
+#define PG_L1_DATA_VADDR (PGTABLE_BASE_VADDR + ((PG_DATA_VBASE >> 20) << 2))
+
+#define PG_L2_DATA_PADDR (PG_L2_LOCKED_PADDR + PG_L2_TEXT_SIZE)
+#define PG_L2_DATA_VADDR (PG_L2_LOCKED_VADDR + PG_L2_TEXT_SIZE)
+#define PG_L2_DATA_SIZE (4*PG_DATA_NPAGES)
+
+/* Page Table Info **********************************************************/
+
+/* The number of pages in the in the page table (PG_PGTABLE_NPAGES). We
+ * position the pagetable PTEs just after the data section PTEs.
+ */
+
+#define PG_PGTABLE_NPAGES (PGTABLE_SIZE >> PAGESHIFT)
+#define PG_L1_PGTABLE_PADDR (PGTABLE_BASE_PADDR + ((PGTABLE_BASE_VADDR >> 20) << 2))
+#define PG_L1_PGTABLE_VADDR (PGTABLE_BASE_VADDR + ((PGTABLE_BASE_VADDR >> 20) << 2))
+
+#define PG_L2_PGTABLE_PADDR (PG_L2_DATA_PADDR + PG_L2_DATA_SIZE)
+#define PG_L2_PGTABLE_VADDR (PG_L2_DATA_VADDR + PG_L2_DATA_SIZE)
+#define PG_L2_PGTABLE_SIZE (4*PG_DATA_NPAGES)
+
+/* Vector Mapping ***********************************************************/
+
+/* One page is required to map the vector table. The vector table could lie
+ * at virtual address zero (or at the start of RAM which is aliased to address
+ * zero on the ea3131) or at virtual address 0xfff00000. We only have logic
+ * here to support the former case.
+ *
+ * NOTE: If the vectors are at address zero, the page table will be
+ * forced to the highest RAM addresses. If the vectors are at 0xfff0000,
+ * then the page table is forced to the beginning of RAM.
+ *
+ * When the vectors are at the beginning of RAM, they will probably overlap
+ * the first page of the locked text region. In any other case, the
+ * configuration must set CONFIG_PAGING_VECPPAGE to provide the physical
+ * address of the page to use for the vectors.
+ *
+ * When the vectors overlap the first page of the locked text region (the
+ * only case in use so far), then the text page will be temporarily be made
+ * writable in order to copy the vectors.
+ *
+ * PG_VECT_PBASE - This the physical address of the page in memory to be
+ * mapped to the vector address.
+ * PG_L2_VECT_PADDR - This is the physical address of the L2 page table
+ * entry to use for the vector mapping.
+ * PG_L2_VECT_VADDR - This is the virtual address of the L2 page table
+ * entry to use for the vector mapping.
+ */
+
+/* Case 1: The configuration tells us everything */
+
+#if defined(CONFIG_PAGING_VECPPAGE)
+# define PG_VECT_PBASE CONFIG_PAGING_VECPPAGE
+# define PG_L2_VECT_PADDR CONFIG_PAGING_VECL2PADDR
+# define PG_L2_VECT_VADDR CONFIG_PAGING_VECL2VADDR
+
+/* Case 2: Vectors are in low memory and the locked text region starts at
+ * the beginning of SRAM (which will be aliased to address 0x00000000).
+ * However, the beginning of SRAM may not be aligned to the beginning
+ * of the L2 page table (because the beginning of RAM is offset into
+ * the table.
+ */
+
+#elif defined(CONFIG_ARCH_LOWVECTORS) && !defined(CONFIG_PAGING_LOCKED_PBASE)
+# define PG_VECT_PBASE PG_LOCKED_PBASE
+# define PG_L2_VECT_OFFSET (((PG_LOCKED_VBASE & 0x000fffff) >> PAGESHIFT) << 2)
+# define PG_L2_VECT_PADDR (PGTABLE_L2_BASE_PADDR + PG_L2_VECT_OFFSET)
+# define PG_L2_VECT_VADDR (PGTABLE_L2_BASE_VADDR + PG_L2_VECT_OFFSET)
+
+/* Case 3: High vectors or the locked region is not at the beginning or SRAM */
+
+#else
+# error "Logic missing for high vectors in this case"
+#endif
+
+/* Page Usage ***************************************************************/
+
+/* This is the total number of pages used in the text/data mapping: */
+
+#define PG_TOTAL_NPPAGES (PG_TEXT_NPPAGES + PG_DATA_NPAGES + PG_PGTABLE_NPAGES)
+#define PG_TOTAL_NVPAGES (PG_TEXT_NVPAGES + PG_DATA_NPAGES + PG_PGTABLE_NPAGES)
+#define PG_TOTAL_PSIZE (PG_TOTAL_NPPAGES << PAGESHIFT)
+#define PG_TOTAL_VSIZE (PG_TOTAL_NVPAGES << PAGESHIFT)
+
+/* Sanity check: */
+
+#if PG_TOTAL_NPPAGES > PG_RAM_PAGES
+# error "Total pages required exceeds RAM size"
+#endif
+
+/* Page Management **********************************************************/
+
+/* For page managment purposes, the following summarize the "heap" of
+ * free pages, operations on free pages and the L2 page table.
+ *
+ * PG_POOL_VA2L1OFFSET(va) - Given a virtual address, return the L1 table
+ * offset (in bytes).
+ * PG_POOL_VA2L1VADDR(va) - Given a virtual address, return the virtual
+ * address of the L1 table entry
+ * PG_POOL_L12PPTABLE(L1) - Given the value of an L1 table entry return
+ * the physical address of the start of the L2
+ * page table
+ * PG_POOL_L12PPTABLE(L1) - Given the value of an L1 table entry return
+ * the virtual address of the start of the L2
+ * page table.
+ *
+ * PG_POOL_L1VBASE - The virtual address of the start of the L1
+ * page table range corresponding to the first
+ * virtual address of the paged text region.
+ * PG_POOL_L1VEND - The virtual address of the end+1 of the L1
+ * page table range corresponding to the last
+ * virtual address+1 of the paged text region.
+ *
+ * PG_POOL_VA2L2NDX(va) - Converts a virtual address within the paged
+ * text region to the most compact possible
+ * representation. Each PAGESIZE of address
+ * corresponds to 1 index in the L2 page table;
+ * Index 0 corresponds to the first L2 page table
+ * entry for the first page in the virtual paged
+ * text address space.
+ * PG_POOL_NDX2VA(ndx) - Performs the opposite conversion.. convests
+ * an index into a virtual address in the paged
+ * text region (the address at the beginning of
+ * the page).
+ * PG_POOL_MAXL2NDX - This is the maximum value+1 of such an index.
+ *
+ * PG_POOL_PGPADDR(ndx) - Converts an page index into the corresponding
+ * (physical) address of the backing page memory.
+ * PG_POOL_PGVADDR(ndx) - Converts an page index into the corresponding
+ * (virtual)address of the backing page memory.
+ *
+ * These are used as follows: If a miss occurs at some virtual address, va,
+ * A new page index, ndx, is allocated. PG_POOL_PGPADDR(i) converts the index
+ * into the physical address of the page memory; PG_POOL_L2VADDR(va) converts
+ * the virtual address in the L2 page table there the new mapping will be
+ * written.
+ */
+
+#define PG_POOL_VA2L1OFFSET(va) (((va) >> 20) << 2)
+#define PG_POOL_VA2L1VADDR(va) (PGTABLE_BASE_VADDR + PG_POOL_VA2L1OFFSET(va))
+#define PG_POOL_L12PPTABLE(L1) ((L1) & PG_L1_PADDRMASK)
+#define PG_POOL_L12VPTABLE(L1) (PG_POOL_L12PPTABLE(L1) - PGTABLE_BASE_PADDR + PGTABLE_BASE_VADDR)
+
+#define PG_POOL_L1VBASE (PGTABLE_BASE_VADDR + ((PG_PAGED_VBASE >> 20) << 2))
+#define PG_POOL_L1VEND (PG_POOL_L1VBASE + (CONFIG_PAGING_NVPAGED << 2))
+
+#define PG_POOL_VA2L2NDX(va) (((va) - PG_PAGED_VBASE) >> PAGESHIFT)
+#define PG_POOL_NDX2VA(ndx) (((ndx) << PAGESHIFT) + PG_PAGED_VBASE)
+#define PG_POOL_MAXL2NDX PG_POOL_VA2L2NDX(PG_PAGED_VEND)
+
+#define PG_POOL_PGPADDR(ndx) (PG_PAGED_PBASE + ((ndx) << PAGESHIFT))
+#define PG_POOL_PGVADDR(ndx) (PG_PAGED_VBASE + ((ndx) << PAGESHIFT))
+
+#endif /* CONFIG_PAGING */
+
+/****************************************************************************
+ * Assembly Macros
+ ****************************************************************************/
+
+#ifdef __ASSEMBLY__
+
+/****************************************************************************
+ * Name: pg_l2map
+ *
+ * Description:
+ * Write several, contiguous L2 page table entries. npages entries will be
+ * written. This macro is used when CONFIG_PAGING is enable. This case,
+ * it is used asfollows:
+ *
+ * ldr r0, =PGTABLE_L2_BASE_PADDR <-- Address in L2 table
+ * ldr r1, =PG_LOCKED_PBASE <-- Physical page memory address
+ * ldr r2, =CONFIG_PAGING_NLOCKED <-- number of pages
+ * ldr r3, =MMUFLAGS <-- L2 MMU flags
+ * pg_l2map r0, r1, r2, r3, r4
+ *
+ * Inputs:
+ * l2 - Physical or virtual start address in the L2 page table, depending
+ * upon the context. (modified)
+ * ppage - The physical address of the start of the region to span. Must
+ * be aligned to 1Mb section boundaries (modified)
+ * npages - Number of pages to write in the section (modified)
+ * mmuflags - L2 MMU FLAGS
+ *
+ * Scratch registers (modified): tmp
+ * l2 - Next address in the L2 page table.
+ * ppage - Start of next physical page
+ * npages - Loop counter
+ * tmp - scratch
+ *
+ * Assumptions:
+ * - The MMU is not yet enabled
+ * - The L2 page tables have been zeroed prior to calling this function
+ * - pg_l1span has been called to initialize the L1 table.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PAGING
+ .macro pg_l2map, l2, ppage, npages, mmuflags, tmp
+ b 2f
+1:
+ /* Write the one L2 entries. First, get tmp = (ppage | mmuflags),
+ * the value to write into the L2 PTE
+ */
+
+ orr \tmp, \ppage, \mmuflags
+
+ /* Write value into table at the current table address
+ * (and increment the L2 page table address by 4)
+ */
+
+ str \tmp, [\l2], #4
+
+ /* Update the physical address that will correspond to the next
+ * table entry.
+ */
+
+ add \ppage, \ppage, #CONFIG_PAGING_PAGESIZE
+
+ /* Decrement the number of pages written */
+
+ sub \npages, \npages, #1
+2:
+ /* Check if all of the pages have been written. If not, then
+ * loop and write the next PTE.
+ */
+ cmp \npages, #0
+ bgt 1b
+ .endm
+#endif /* CONFIG_PAGING */
+
+/****************************************************************************
+ * Name: pg_l1span
+ *
+ * Description:
+ * Write several, contiguous unmapped coarse L1 page table entries. As
+ * many entries will be written as many as needed to span npages. This
+ * macro is used when CONFIG_PAGING is enable. This case, it is used as
+ * follows:
+ *
+ * ldr r0, =PG_L1_PGTABLE_PADDR <-- Address in the L1 table
+ * ldr r1, =PG_L2_PGTABLE_PADDR <-- Physical address of L2 page table
+ * ldr r2, =PG_PGTABLE_NPAGES <-- Total number of pages
+ * ldr r3, =PG_PGTABLE_NPAGE1 <-- Number of pages in the first PTE
+ * ldr r4, =MMU_L1_PGTABFLAGS <-- L1 MMU flags
+ * pg_l1span r0, r1, r2, r3, r4, r4
+ *
+ * Inputs (unmodified unless noted):
+ * l1 - Physical or virtual address in the L1 table to begin writing (modified)
+ * l2 - Physical start address in the L2 page table (modified)
+ * npages - Number of pages to required to span that memory region (modified)
+ * ppage - The number of pages in page 1 (modified)
+ * mmuflags - L1 MMU flags to use
+ *
+ * Scratch registers (modified): l1, l2, npages, tmp
+ * l1 - Next L1 table address
+ * l2 - Physical start address of the next L2 page table
+ * npages - Loop counter
+ * ppage - After the first page, this will be the full number of pages.
+ * tmp - scratch
+ *
+ * Return:
+ * Nothing of interest.
+ *
+ * Assumptions:
+ * - The MMU is not yet enabled
+ * - The L2 page tables have been zeroed prior to calling this function
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PAGING
+ .macro pg_l1span, l1, l2, npages, ppage, mmuflags, tmp
+ b 2f
+1:
+ /* Write the L1 table entry that refers to this (unmapped) coarse page
+ * table.
+ *
+ * tmp = (l2table | mmuflags), the value to write into the page table
+ */
+
+ orr \tmp, \l2, \mmuflags
+
+ /* Write the value into the L1 table at the correct offset.
+ * (and increment the L1 table address by 4)
+ */
+
+ str \tmp, [\l1], #4
+
+ /* Update the L2 page table address for the next L1 table entry. */
+
+ add \l2, \l2, #PT_SIZE /* Next L2 page table start address */
+
+ /* Update the number of pages that we have account for (with
+ * non-mappings). NOTE that the first page may have fewer than
+ * the maximum entries per page table.
+ */
+
+ sub \npages, \npages, \ppage
+ mov \ppage, #PTE_NPAGES
+2:
+ /* Check if all of the pages have been written. If not, then
+ * loop and write the next L1 entry.
+ */
+
+ cmp \npages, #0
+ bgt 1b
+ .endm
+
+#endif /* CONFIG_PAGING */
+#endif /* __ASSEMBLY__ */
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_ARM_PG_MACROS_H */
diff --git a/nuttx/arch/arm/src/arm/up_allocpage.c b/nuttx/arch/arm/src/arm/up_allocpage.c
new file mode 100755
index 000000000..c2a31d09c
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_allocpage.c
@@ -0,0 +1,243 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_allocpage.c
+ * Allocate a new page and map it to the fault address of a task.
+ *
+ * Copyright (C) 2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <stdbool.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/sched.h>
+
+#ifdef CONFIG_PAGING
+
+#include <nuttx/page.h>
+
+#include "pg_macros.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#if CONFIG_PAGING_NPPAGED < 256
+typedef uint8_t pgndx_t;
+#elif CONFIG_PAGING_NPPAGED < 65536
+typedef uint16_t pgndx_t;
+#else
+typedef uint32_t pgndx_t;
+#endif
+
+#if PG_POOL_MAXL1NDX < 256
+typedef uint8_t L1ndx_t;
+#elif PG_POOL_MAXL1NDX < 65536
+typedef uint16_t L1ndx_t;
+#else
+typedef uint32_t L1ndx_t;
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Free pages in memory are managed by indices ranging from up to
+ * CONFIG_PAGING_NPAGED. Initially all pages are free so the page can be
+ * simply allocated in order: 0, 1, 2, ... . After all CONFIG_PAGING_NPAGED
+ * pages have be filled, then they are blindly freed and re-used in the
+ * same order 0, 1, 2, ... because we don't know any better. No smart "least
+ * recently used" kind of logic is supported.
+ */
+
+static pgndx_t g_pgndx;
+
+/* After CONFIG_PAGING_NPAGED have been allocated, the pages will be re-used.
+ * In order to re-used the page, we will have un-map the page from its previous
+ * mapping. In order to that, we need to be able to map a physical address to
+ * to an index into the PTE where it was mapped. The following table supports
+ * this backward lookup - it is indexed by the page number index, and holds
+ * another index to the mapped virtual page.
+ */
+
+static L1ndx_t g_ptemap[CONFIG_PAGING_NPPAGED];
+
+/* The contents of g_ptemap[] are not valid until g_pgndx has wrapped at
+ * least one time.
+ */
+
+static bool g_pgwrap;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocpage()
+ *
+ * Description:
+ * This architecture-specific function will set aside page in memory and map
+ * the page to its correct virtual address. Architecture-specific context
+ * information saved within the TCB will provide the function with the
+ * information needed to identify the virtual miss address.
+ *
+ * This function will return the allocated physical page address in vpage.
+ * The size of the underlying physical page is determined by the
+ * configuration setting CONFIG_PAGING_PAGESIZE.
+ *
+ * NOTE 1: This function must always return a page allocation. If all
+ * available pages are in-use (the typical case), then this function will
+ * select a page in-use, un-map it, and make it available.
+ *
+ * NOTE 2: If an in-use page is un-mapped, it may be necessary to flush the
+ * instruction cache in some architectures.
+ *
+ * NOTE 3: Allocating and filling a page is a two step process. up_allocpage()
+ * allocates the page, and up_fillpage() fills it with data from some non-
+ * volatile storage device. This distinction is made because up_allocpage()
+ * can probably be implemented in board-independent logic whereas up_fillpage()
+ * probably must be implemented as board-specific logic.
+ *
+ * NOTE 4: The initial mapping of vpage should be read-able and write-
+ * able (but not cached). No special actions will be required of
+ * up_fillpage() in order to write into this allocated page.
+ *
+ * Input Parameters:
+ * tcb - A reference to the task control block of the task that needs to
+ * have a page fill. Architecture-specific logic can retrieve page
+ * fault information from the architecture-specific context
+ * information in this TCB to perform the mapping.
+ *
+ * Returned Value:
+ * This function will return zero (OK) if the allocation was successful.
+ * A negated errno value may be returned if an error occurs. All errors,
+ * however, are fatal.
+ *
+ * Assumptions:
+ * - This function is called from the normal tasking context (but with
+ * interrupts disabled). The implementation must take whatever actions
+ * are necessary to assure that the operation is safe within this
+ * context.
+ *
+ ****************************************************************************/
+
+int up_allocpage(FAR _TCB *tcb, FAR void **vpage)
+{
+ uintptr_t vaddr;
+ uintptr_t paddr;
+ uint32_t *pte;
+ unsigned int pgndx;
+
+ /* Since interrupts are disabled, we don't need to anything special. */
+
+ DEBUGASSERT(tcb && vpage);
+
+ /* Get the virtual address that caused the fault */
+
+ vaddr = tcb->xcp.far;
+ DEBUGASSERT(vaddr >= PG_PAGED_VBASE && vaddr < PG_PAGED_VEND);
+
+ /* Allocate page memory to back up the mapping. Start by getting the
+ * index of the next page that we are going to allocate.
+ */
+
+ pgndx = g_pgndx++;
+ if (g_pgndx >= CONFIG_PAGING)
+ {
+ g_pgndx = 0;
+ g_pgwrap = true;
+ }
+
+ /* Was this physical page previously mapped? If so, then we need to un-map
+ * it.
+ */
+
+ if (g_pgwrap)
+ {
+ /* Yes.. Get a pointer to the L2 entry corresponding to the previous
+ * mapping -- then zero it!
+ */
+
+ uintptr_t oldvaddr = PG_POOL_NDX2VA(g_ptemap[pgndx]);
+ pte = up_va2pte(oldvaddr);
+ *pte = 0;
+
+ /* Invalidate the instruction TLB corresponding to the virtual address */
+
+ tlb_inst_invalidate_single(oldvaddr);
+
+ /* I do not believe that it is necessary to flush the I-Cache in this
+ * case: The I-Cache uses a virtual address index and, hence, since the
+ * NuttX address space is flat, the cached instruction value should be
+ * correct even if the page mapping is no longer in place.
+ */
+ }
+
+ /* Then convert the index to a (physical) page address. */
+
+ paddr = PG_POOL_PGPADDR(pgndx);
+
+ /* Now setup up the new mapping. Get a pointer to the L2 entry
+ * corresponding to the new mapping. Then set it map to the newly
+ * allocated page address. The inital mapping is read/write but
+ * non-cached (MMU_L2_ALLOCFLAGS)
+ */
+
+ pte = up_va2pte(vaddr);
+ *pte = (paddr | MMU_L2_ALLOCFLAGS);
+
+ /* And save the new L1 index */
+
+ g_ptemap[pgndx] = PG_POOL_VA2L2NDX(vaddr);
+
+ /* Finally, return the virtual address of allocated page */
+
+ *vpage = (void*)(vaddr & ~PAGEMASK);
+ return OK;
+}
+
+#endif /* CONFIG_PAGING */
diff --git a/nuttx/arch/arm/src/arm/up_assert.c b/nuttx/arch/arm/src/arm/up_assert.c
new file mode 100644
index 000000000..f52dc1b94
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_assert.c
@@ -0,0 +1,325 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_assert.c
+ *
+ * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <stdlib.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Output debug info if stack dump is selected -- even if
+ * debug is not selected.
+ */
+
+#ifdef CONFIG_ARCH_STACKDUMP
+# undef lldbg
+# define lldbg lib_lowprintf
+#endif
+
+/* The following is just intended to keep some ugliness out of the mainline
+ * code. We are going to print the task name if:
+ *
+ * CONFIG_TASK_NAME_SIZE > 0 && <-- The task has a name
+ * (defined(CONFIG_DEBUG) || <-- And the debug is enabled (lldbg used)
+ * defined(CONFIG_ARCH_STACKDUMP) <-- Or lib_lowprintf() is used
+ */
+
+#undef CONFIG_PRINT_TASKNAME
+#if CONFIG_TASK_NAME_SIZE > 0 && (defined(CONFIG_DEBUG) || defined(CONFIG_ARCH_STACKDUMP))
+# define CONFIG_PRINT_TASKNAME 1
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_getsp
+ ****************************************************************************/
+
+/* I don't know if the builtin to get SP is enabled */
+
+static inline uint32_t up_getsp(void)
+{
+ uint32_t sp;
+ __asm__
+ (
+ "\tmov %0, sp\n\t"
+ : "=r"(sp)
+ );
+ return sp;
+}
+
+/****************************************************************************
+ * Name: up_stackdump
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_STACKDUMP
+static void up_stackdump(uint32_t sp, uint32_t stack_base)
+{
+ uint32_t stack ;
+
+ for (stack = sp & ~0x1f; stack < stack_base; stack += 32)
+ {
+ uint32_t *ptr = (uint32_t*)stack;
+ lldbg("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ stack, ptr[0], ptr[1], ptr[2], ptr[3],
+ ptr[4], ptr[5], ptr[6], ptr[7]);
+ }
+}
+#else
+# define up_stackdump()
+#endif
+
+/****************************************************************************
+ * Name: up_registerdump
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_STACKDUMP
+static inline void up_registerdump(void)
+{
+ /* Are user registers available from interrupt processing? */
+
+ if (current_regs)
+ {
+ int regs;
+
+ /* Yes.. dump the interrupt registers */
+
+ for (regs = REG_R0; regs <= REG_R15; regs += 8)
+ {
+ uint32_t *ptr = (uint32_t*)&current_regs[regs];
+ lldbg("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ regs, ptr[0], ptr[1], ptr[2], ptr[3],
+ ptr[4], ptr[5], ptr[6], ptr[7]);
+ }
+
+ lldbg("CPSR: %08x\n", current_regs[REG_CPSR]);
+ }
+}
+#else
+# define up_registerdump()
+#endif
+
+/****************************************************************************
+ * Name: up_dumpstate
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_STACKDUMP
+static void up_dumpstate(void)
+{
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+ uint32_t sp = up_getsp();
+ uint32_t ustackbase;
+ uint32_t ustacksize;
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ uint32_t istackbase;
+ uint32_t istacksize;
+#endif
+
+ /* Get the limits on the user stack memory */
+
+ if (rtcb->pid == 0)
+ {
+ ustackbase = g_heapbase - 4;
+ ustacksize = CONFIG_IDLETHREAD_STACKSIZE;
+ }
+ else
+ {
+ ustackbase = (uint32_t)rtcb->adj_stack_ptr;
+ ustacksize = (uint32_t)rtcb->adj_stack_size;
+ }
+
+ /* Get the limits on the interrupt stack memory */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ istackbase = (uint32_t)&g_userstack;
+ istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4;
+
+ /* Show interrupt stack info */
+
+ lldbg("sp: %08x\n", sp);
+ lldbg("IRQ stack:\n");
+ lldbg(" base: %08x\n", istackbase);
+ lldbg(" size: %08x\n", istacksize);
+
+ /* Does the current stack pointer lie within the interrupt
+ * stack?
+ */
+
+ if (sp <= istackbase && sp > istackbase - istacksize)
+ {
+ /* Yes.. dump the interrupt stack */
+
+ up_stackdump(sp, istackbase);
+
+ /* Extract the user stack pointer which should lie
+ * at the base of the interrupt stack.
+ */
+
+ sp = g_userstack;
+ lldbg("sp: %08x\n", sp);
+ }
+
+ /* Show user stack info */
+
+ lldbg("User stack:\n");
+ lldbg(" base: %08x\n", ustackbase);
+ lldbg(" size: %08x\n", ustacksize);
+#else
+ lldbg("sp: %08x\n", sp);
+ lldbg("stack base: %08x\n", ustackbase);
+ lldbg("stack size: %08x\n", ustacksize);
+#endif
+
+ /* Dump the user stack if the stack pointer lies within the allocated user
+ * stack memory.
+ */
+
+ if (sp > ustackbase || sp <= ustackbase - ustacksize)
+ {
+#if !defined(CONFIG_ARCH_INTERRUPTSTACK) || CONFIG_ARCH_INTERRUPTSTACK < 4
+ lldbg("ERROR: Stack pointer is not within allocated stack\n");
+#endif
+ }
+ else
+ {
+ up_stackdump(sp, ustackbase);
+ }
+
+ /* Then dump the registers (if available) */
+
+ up_registerdump();
+}
+#else
+# define up_dumpstate()
+#endif
+
+/****************************************************************************
+ * Name: _up_assert
+ ****************************************************************************/
+
+static void _up_assert(int errorcode) /* __attribute__ ((noreturn)) */
+{
+ /* Are we in an interrupt handler or the idle task? */
+
+ if (current_regs || ((_TCB*)g_readytorun.head)->pid == 0)
+ {
+ (void)irqsave();
+ for(;;)
+ {
+#ifdef CONFIG_ARCH_LEDS
+ up_ledon(LED_PANIC);
+ up_mdelay(250);
+ up_ledoff(LED_PANIC);
+ up_mdelay(250);
+#endif
+ }
+ }
+ else
+ {
+ exit(errorcode);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_assert
+ ****************************************************************************/
+
+void up_assert(const uint8_t *filename, int lineno)
+{
+#ifdef CONFIG_PRINT_TASKNAME
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+#endif
+
+ up_ledon(LED_ASSERTION);
+#ifdef CONFIG_PRINT_TASKNAME
+ lldbg("Assertion failed at file:%s line: %d task: %s\n",
+ filename, lineno, rtcb->name);
+#else
+ lldbg("Assertion failed at file:%s line: %d\n",
+ filename, lineno);
+#endif
+ up_dumpstate();
+ _up_assert(EXIT_FAILURE);
+}
+
+/****************************************************************************
+ * Name: up_assert_code
+ ****************************************************************************/
+
+void up_assert_code(const uint8_t *filename, int lineno, int errorcode)
+{
+#ifdef CONFIG_PRINT_TASKNAME
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+#endif
+
+ up_ledon(LED_ASSERTION);
+
+#ifdef CONFIG_PRINT_TASKNAME
+ lldbg("Assertion failed at file:%s line: %d task: %s error code: %d\n",
+ filename, lineno, rtcb->name, errorcode);
+#else
+ lldbg("Assertion failed at file:%s line: %d error code: %d\n",
+ filename, lineno, errorcode);
+#endif
+ up_dumpstate();
+ _up_assert(errorcode);
+}
diff --git a/nuttx/arch/arm/src/arm/up_blocktask.c b/nuttx/arch/arm/src/arm/up_blocktask.c
new file mode 100755
index 000000000..36c8740d6
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_blocktask.c
@@ -0,0 +1,167 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_blocktask.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <stdbool.h>
+#include <sched.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_block_task
+ *
+ * Description:
+ * The currently executing task at the head of
+ * the ready to run list must be stopped. Save its context
+ * and move it to the inactive list specified by task_state.
+ *
+ * Inputs:
+ * tcb: Refers to a task in the ready-to-run list (normally
+ * the task at the head of the list). It most be
+ * stopped, its context saved and moved into one of the
+ * waiting task lists. It it was the task at the head
+ * of the ready-to-run list, then a context to the new
+ * ready to run task must be performed.
+ * task_state: Specifies which waiting task list should be
+ * hold the blocked task TCB.
+ *
+ ****************************************************************************/
+
+void up_block_task(_TCB *tcb, tstate_t task_state)
+{
+ /* Verify that the context switch can be performed */
+
+ if ((tcb->task_state < FIRST_READY_TO_RUN_STATE) ||
+ (tcb->task_state > LAST_READY_TO_RUN_STATE))
+ {
+ PANIC(OSERR_BADBLOCKSTATE);
+ }
+ else
+ {
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+ bool switch_needed;
+
+ /* Remove the tcb task from the ready-to-run list. If we
+ * are blocking the task at the head of the task list (the
+ * most likely case), then a context switch to the next
+ * ready-to-run task is needed. In this case, it should
+ * also be true that rtcb == tcb.
+ */
+
+ switch_needed = sched_removereadytorun(tcb);
+
+ /* Add the task to the specified blocked task list */
+
+ sched_addblocked(tcb, (tstate_t)task_state);
+
+ /* If there are any pending tasks, then add them to the g_readytorun
+ * task list now
+ */
+
+ if (g_pendingtasks.head)
+ {
+ switch_needed |= sched_mergepending();
+ }
+
+ /* Now, perform the context switch if one is needed */
+
+ if (switch_needed)
+ {
+ /* Are we in an interrupt handler? */
+
+ if (current_regs)
+ {
+ /* Yes, then we have to do things differently.
+ * Just copy the current_regs into the OLD rtcb.
+ */
+
+ up_savestate(rtcb->xcp.regs);
+
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+
+ /* Then switch contexts */
+
+ up_restorestate(rtcb->xcp.regs);
+ }
+
+ /* Copy the user C context into the TCB at the (old) head of the
+ * g_readytorun Task list. if up_saveusercontext returns a non-zero
+ * value, then this is really the previously running task restarting!
+ */
+
+ else if (!up_saveusercontext(rtcb->xcp.regs))
+ {
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+
+ /* Then switch contexts */
+
+ up_fullcontextrestore(rtcb->xcp.regs);
+ }
+ }
+ }
+}
diff --git a/nuttx/arch/arm/src/arm/up_cache.S b/nuttx/arch/arm/src/arm/up_cache.S
new file mode 100644
index 000000000..05926fbb4
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_cache.S
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_cache.S
+ *
+ * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 "up_internal.h"
+#include "up_arch.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define CACHE_DLINESIZE 32
+
+/****************************************************************************
+ * Assembly Macros
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_flushicache
+ ****************************************************************************/
+
+/* Esure coherency between the Icache and the Dcache in the region described
+ * by r0=start and r1=end.
+ */
+ .globl up_flushicache
+ .type up_flushicache,%function
+up_flushicache:
+ bic r0, r0, #CACHE_DLINESIZE - 1
+1: mcr p15, 0, r0, c7, c10, 1 /* Clean D entry */
+ mcr p15, 0, r0, c7, c5, 1 /* Invalidate I entry */
+ add r0, r0, #CACHE_DLINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, r0, c7, c10, 4 /* Drain WB */
+ mov pc, lr
+ .size up_flushicache, .-up_flushicache
+ .end
+
diff --git a/nuttx/arch/arm/src/arm/up_checkmapping.c b/nuttx/arch/arm/src/arm/up_checkmapping.c
new file mode 100755
index 000000000..370c94c9d
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_checkmapping.c
@@ -0,0 +1,123 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_checkmapping.c
+ * Check if the current task's fault address has been mapped into the virtual
+ * address space.
+ *
+ * Copyright (C) 2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <nuttx/sched.h>
+#include <nuttx/page.h>
+
+#include "up_internal.h"
+
+#ifdef CONFIG_PAGING
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_checkmapping()
+ *
+ * Description:
+ * The function up_checkmapping() returns an indication if the page fill
+ * still needs to performed or not. In certain conditions, the page fault
+ * may occur on several threads and be queued multiple times. This function
+ * will prevent the same page from be filled multiple times.
+ *
+ * Input Parameters:
+ * tcb - A reference to the task control block of the task that we believe
+ * needs to have a page fill. Architecture-specific logic can
+ * retrieve page fault information from the architecture-specific
+ * context information in this TCB and can consult processor resources
+ * (page tables or TLBs or ???) to determine if the fill still needs
+ * to be performed or not.
+ *
+ * Returned Value:
+ * This function will return true if the mapping is in place and false
+ * if the mapping is still needed. Errors encountered should be
+ * interpreted as fatal.
+ *
+ * Assumptions:
+ * - This function is called from the normal tasking context (but with
+ * interrupts disabled). The implementation must take whatever actions
+ * are necessary to assure that the operation is safe within this
+ * context.
+ *
+ ****************************************************************************/
+
+bool up_checkmapping(FAR _TCB *tcb)
+{
+ uintptr_t vaddr;
+ uint32_t *pte;
+
+ /* Since interrupts are disabled, we don't need to anything special. */
+
+ DEBUGASSERT(tcb);
+
+ /* Get the virtual address that caused the fault */
+
+ vaddr = tcb->xcp.far;
+ DEBUGASSERT(vaddr >= PG_PAGED_VBASE && vaddr < PG_PAGED_VEND);
+
+ /* Get the PTE associated with this virtual address */
+
+ pte = up_va2pte(vaddr);
+
+ /* Return true if this virtual address is mapped. */
+
+ return (*pte != 0);
+}
+
+#endif /* CONFIG_PAGING */
diff --git a/nuttx/arch/arm/src/arm/up_copystate.c b/nuttx/arch/arm/src/arm/up_copystate.c
new file mode 100644
index 000000000..44f027b32
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_copystate.c
@@ -0,0 +1,82 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_copystate.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_undefinedinsn
+ ****************************************************************************/
+
+/* A little faster than most memcpy's */
+
+void up_copystate(uint32_t *dest, uint32_t *src)
+{
+ int i;
+
+ /* In the current ARM model, the state is always copied to and from the
+ * stack and TCB.
+ */
+
+ for (i = 0; i < XCPTCONTEXT_REGS; i++)
+ {
+ *dest++ = *src++;
+ }
+}
+
diff --git a/nuttx/arch/arm/src/arm/up_dataabort.c b/nuttx/arch/arm/src/arm/up_dataabort.c
new file mode 100644
index 000000000..c36970c1b
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_dataabort.c
@@ -0,0 +1,201 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_dataabort.c
+ *
+ * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <nuttx/irq.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+#ifdef CONFIG_PAGING
+# include <nuttx/page.h>
+# include "arm.h"
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Output debug info if stack dump is selected -- even if
+ * debug is not selected.
+ */
+
+#ifdef CONFIG_ARCH_STACKDUMP
+# undef lldbg
+# define lldbg lib_lowprintf
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_dataabort
+ *
+ * Input parameters:
+ * regs - The standard, ARM register save array.
+ *
+ * If CONFIG_PAGING is selected in the NuttX configuration file, then these
+ * additional input values are expected:
+ *
+ * far - Fault address register. On a data abort, the ARM MMU places the
+ * miss virtual address (MVA) into the FAR register. This is the address
+ * of the data which, when accessed, caused the fault.
+ * fsr - Fault status register. On a data a abort, the ARM MMU places an
+ * encoded four-bit value, the fault status, along with the four-bit
+ * encoded domain number, in the data FSR
+ *
+ * Description:
+ * This is the data abort exception handler. The ARM data abort exception
+ * occurs when a memory fault is detected during a data transfer.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PAGING
+void up_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr)
+{
+ FAR _TCB *tcb = (FAR _TCB *)g_readytorun.head;
+#ifdef CONFIG_PAGING
+ uint32_t *savestate;
+
+ /* Save the saved processor context in current_regs where it can be accessed
+ * for register dumps and possibly context switching.
+ */
+
+
+ savestate = (uint32_t*)current_regs;
+#endif
+ current_regs = regs;
+
+#ifdef CONFIG_PAGING
+ /* In the NuttX on-demand paging implementation, only the read-only, .text
+ * section is paged. However, the ARM compiler generated PC-relative data
+ * fetches from within the .text sections. Also, it is customary to locate
+ * read-only data (.rodata) within the same section as .text so that it
+ * does not require copying to RAM. Misses in either of these case should
+ * cause a data abort.
+ *
+ * We are only interested in data aborts due to page translations faults.
+ * Sections should already be in place and permissions should already be
+ * be set correctly (to read-only) so any other data abort reason is a
+ * fatal error.
+ */
+
+ pglldbg("FSR: %08x FAR: %08x\n", fsr, far);
+ if ((fsr & FSR_MASK) != FSR_PAGE)
+ {
+ goto segfault;
+ }
+
+ /* Check the (virtual) address of data that caused the data abort. When
+ * the exception occurred, this address was provided in the FAR register.
+ * (It has not yet been saved in the register context save area).
+ */
+
+ pgllvdbg("VBASE: %08x VEND: %08x\n", PG_PAGED_VBASE, PG_PAGED_VEND);
+ if (far < PG_PAGED_VBASE || far >= PG_PAGED_VEND)
+ {
+ goto segfault;
+ }
+
+ /* Save the offending data address as the fault address in the TCB of
+ * the currently task. This fault address is also used by the prefetch
+ * abort handling; this will allow common paging logic for both
+ * prefetch and data aborts.
+ */
+
+ tcb->xcp.far = regs[REG_R15];
+
+ /* Call pg_miss() to schedule the page fill. A consequences of this
+ * call are:
+ *
+ * (1) The currently executing task will be blocked and saved on
+ * on the g_waitingforfill task list.
+ * (2) An interrupt-level context switch will occur so that when
+ * this function returns, it will return to a different task,
+ * most likely the page fill worker thread.
+ * (3) The page fill worker task has been signalled and should
+ * execute immediately when we return from this exception.
+ */
+
+ pg_miss();
+
+ /* Restore the previous value of current_regs. NULL would indicate that
+ * we are no longer in an interrupt handler. It will be non-NULL if we
+ * are returning from a nested interrupt.
+ */
+
+ current_regs = savestate;
+ return;
+
+segfault:
+#endif
+ lldbg("Data abort. PC: %08x FAR: %08x FSR: %08x\n", regs[REG_PC], far, fsr);
+ PANIC(OSERR_ERREXCEPTION);
+}
+
+#else /* CONFIG_PAGING */
+
+void up_dataabort(uint32_t *regs)
+{
+ /* Save the saved processor context in current_regs where it can be accessed
+ * for register dumps and possibly context switching.
+ */
+
+ current_regs = regs;
+
+ /* Crash -- possibly showing diagnost debug information. */
+
+ lldbg("Data abort. PC: %08x\n", regs[REG_PC]);
+ PANIC(OSERR_ERREXCEPTION);
+}
+
+#endif /* CONFIG_PAGING */
diff --git a/nuttx/arch/arm/src/arm/up_doirq.c b/nuttx/arch/arm/src/arm/up_doirq.c
new file mode 100644
index 000000000..1f1c77473
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_doirq.c
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_doirq.c
+ *
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <assert.h>
+
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void up_doirq(int irq, uint32_t *regs)
+{
+ up_ledon(LED_INIRQ);
+#ifdef CONFIG_SUPPRESS_INTERRUPTS
+ PANIC(OSERR_ERREXCEPTION);
+#else
+ uint32_t *savestate;
+
+ /* Nested interrupts are not supported in this implementation. If you want
+ * implemented nested interrupts, you would have to (1) change the way that
+ * current regs is handled and (2) the design associated with
+ * CONFIG_ARCH_INTERRUPTSTACK.
+ */
+
+ /* Current regs non-zero indicates that we are processing an interrupt;
+ * current_regs is also used to manage interrupt level context switches.
+ */
+
+ savestate = (uint32_t*)current_regs;
+ current_regs = regs;
+
+ /* Mask and acknowledge the interrupt */
+
+ up_maskack_irq(irq);
+
+ /* Deliver the IRQ */
+
+ irq_dispatch(irq, regs);
+
+ /* Restore the previous value of current_regs. NULL would indicate that
+ * we are no longer in an interrupt handler. It will be non-NULL if we
+ * are returning from a nested interrupt.
+ */
+
+ current_regs = savestate;
+
+ /* Unmask the last interrupt (global interrupts are still disabled) */
+
+ up_enable_irq(irq);
+#endif
+ up_ledoff(LED_INIRQ);
+}
diff --git a/nuttx/arch/arm/src/arm/up_fullcontextrestore.S b/nuttx/arch/arm/src/arm/up_fullcontextrestore.S
new file mode 100644
index 000000000..d0745ef5b
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_fullcontextrestore.S
@@ -0,0 +1,118 @@
+/**************************************************************************
+ * arch/arm/src/arm/up_fullcontextrestore.S
+ *
+ * Copyright (C) 2007, 2009-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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/irq.h>
+#include "up_internal.h"
+
+/**************************************************************************
+ * Private Definitions
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Types
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Function Prototypes
+ **************************************************************************/
+
+/**************************************************************************
+ * Global Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Public Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Name: up_fullcontextrestore
+ **************************************************************************/
+
+ .globl up_fullcontextrestore
+ .type up_fullcontextrestore, function
+up_fullcontextrestore:
+
+ /* On entry, a1 (r0) holds address of the register save area */
+
+ /* Recover all registers except for r0, r1, R15, and CPSR */
+
+ add r1, r0, #(4*REG_R2) /* Offset to REG_R2 storage */
+ ldmia r1, {r2-r14} /* Recover registers */
+
+ /* Create a stack frame to hold the PC */
+
+ sub sp, sp, #(3*4) /* Frame for three registers */
+ ldr r1, [r0, #(4*REG_R0)] /* Fetch the stored r0 value */
+ str r1, [sp] /* Save it at the top of the stack */
+ ldr r1, [r0, #(4*REG_R1)] /* Fetch the stored r1 value */
+ str r1, [sp, #4] /* Save it in the stack */
+ ldr r1, [r0, #(4*REG_PC)] /* Fetch the stored pc value */
+ str r1, [sp, #8] /* Save it at the bottom of the frame */
+
+ /* Now we can restore the CPSR. We wait until we are completely
+ * finished with the context save data to do this. Restore the CPSR
+ * may re-enable and interrupts and we could be in a context
+ * where the save structure is only protected by interrupts being
+ * disabled.
+ */
+
+ ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the stored CPSR value */
+ msr cpsr, r1 /* Set the CPSR */
+
+ /* Now recover r0 and r1 */
+
+ ldr r0, [sp]
+ ldr r1, [sp, #4]
+ add sp, sp, #(2*4)
+
+ /* Then return to the address at the stop of the stack,
+ * destroying the stack frame
+ */
+
+ ldr pc, [sp], #4
+ .size up_fullcontextrestore, . - up_fullcontextrestore
+
diff --git a/nuttx/arch/arm/src/arm/up_head.S b/nuttx/arch/arm/src/arm/up_head.S
new file mode 100644
index 000000000..c04dddf8a
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_head.S
@@ -0,0 +1,638 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_head.S
+ *
+ * Copyright (C) 2007, 2009-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 "arm.h"
+#include "chip.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+#ifdef CONFIG_PAGING
+# include <nuttx/page.h>
+# include "pg_macros.h"
+#endif
+
+/**********************************************************************************
+ * Configuration
+ **********************************************************************************/
+
+#undef ALIGNMENT_TRAP
+#undef CPU_DCACHE_WRITETHROUGH
+#undef CPU_CACHE_ROUND_ROBIN
+#undef CPU_DCACHE_DISABLE
+#undef CPU_ICACHE_DISABLE
+
+/* There are three operational memory configurations:
+ *
+ * 1. We execute in place in FLASH (CONFIG_BOOT_RUNFROMFLASH=y). In this case
+ * the boot logic must:
+ *
+ * - Configure SDRAM,
+ * - Initialize the .data section in RAM, and
+ * - Clear .bss section
+ */
+
+#ifdef CONFIG_BOOT_RUNFROMFLASH
+# error "Configuration not implemented"
+# define CONFIG_SDRAM 1
+
+ /* Check for the identity mapping: For this configuration, this would be
+ * the case where the virtual beginning of FLASH is the same as the physical
+ * beginning of FLASH.
+ */
+
+# if CONFIG_FLASH_START == CONFIG_FLASH_VSTART
+# define CONFIG_IDENTITY_TEXTMAP 1
+# endif
+
+/* 2. We boot in FLASH but copy ourselves to DRAM from better performance.
+ * (CONFIG_BOOT_RUNFROMFLASH=n && CONFIG_BOOT_COPYTORAM=y). In this case
+ * the boot logic must:
+ *
+ * - Configure SDRAM,
+ * - Copy ourself to DRAM (after mapping it), and
+ * - Clear .bss section
+ *
+ * In this case, we assume that the logic within this file executes from FLASH.
+ */
+
+#elif defined(CONFIG_BOOT_COPYTORAM)
+# error "configuration not implemented
+# define CONFIG_SDRAM 1
+
+ /* Check for the identity mapping: For this configuration, this would be
+ * the case where the virtual beginning of FLASH is the same as the physical
+ * beginning of FLASH.
+ */
+
+# if CONFIG_FLASH_START == CONFIG_FLASH_VSTART
+# define CONFIG_IDENTITY_TEXTMAP 1
+# endif
+
+/* 3. There is bootloader that copies us to DRAM (but probably not to the beginning)
+ * (CONFIG_BOOT_RUNFROMFLASH=n && CONFIG_BOOT_COPYTORAM=n). In this case SDRAM
+ * was initialized by the boot loader, and this boot logic must:
+ *
+ * - Clear .bss section
+ */
+
+#else
+
+ /* Check for the identity mapping: For this configuration, this would be
+ * the case where the virtual beginning of RAM is the same as the physical
+ * beginning of RAM.
+ */
+
+# if CONFIG_DRAM_START == CONFIG_DRAM_VSTART
+# define CONFIG_IDENTITY_TEXTMAP 1
+# endif
+
+#endif
+
+/* For each page table offset, the following provide (1) the physical address of
+ * the start of the page table and (2) the number of page table entries in the
+ * first page table.
+ *
+ * Coarse: PG_L1_PADDRMASK=0xfffffc00
+ * NPAGE1=(256 -((a) & 0x000003ff) >> 2) NPAGE1=1-256
+ * Fine: PG_L1_PADDRMASK=0xfffff000
+ * NPAGE1=(1024 -((a) & 0x00000fff) >> 2) NPAGE1=1-1024
+ */
+
+#ifdef CONFIG_PAGING
+# define PG_L2_TEXT_PBASE (PG_L2_TEXT_PADDR & PG_L1_PADDRMASK)
+# define PG_L2_TEXT_NPAGE1 (PTE_NPAGES - ((PG_L2_TEXT_PADDR & ~PG_L1_PADDRMASK) >> 2))
+# define PG_L2_PGTABLE_PBASE (PG_L2_PGTABLE_PADDR & PG_L1_PADDRMASK)
+# define PG_L2_PGTABLE_NPAGE1 (PTE_NPAGES - ((PG_L2_PGTABLE_PADDR & ~PG_L1_PADDRMASK) >> 2))
+# define PG_L2_DATA_PBASE (PG_L2_DATA_PADDR & PG_L1_PADDRMASK)
+# define PG_L2_DATA_NPAGE1 (PTE_NPAGES - ((PG_L2_DATA_PADDR & ~PG_L1_PADDRMASK) >> 2))
+#endif
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* RX_NSECTIONS determines the number of 1Mb sections to map for the
+ * Read/eXecute address region. This is based on CONFIG_DRAM_SIZE. For most
+ * ARM9 architectures, CONFIG_DRAM_SIZE describes the size of installed SDRAM.
+ * But for other architectures, this might refer to the size of FLASH or
+ * SRAM regions. (bad choice of naming).
+ */
+
+#define RX_NSECTIONS ((CONFIG_DRAM_SIZE+0x000fffff) >> 20)
+
+/****************************************************************************
+ * Assembly Macros
+ ****************************************************************************/
+
+/* The ARM9 L1 page table can be placed at the beginning or at the end of the
+ * RAM space. This decision is based on the placement of the vector area:
+ * If the vectors are place in low memory at address 0x0000 0000, then the
+ * page table is placed in high memory; if the vectors are placed in high
+ * memory at address 0xfff0 0000, then the page table is locating at the
+ * beginning of RAM.
+ *
+ * For the special case where (1) the program executes out of RAM, and (2) the
+ * page is located at the beginning of RAM, then the following macro can
+ * easily find the physical address of the section that includes the first
+ * part of the text region: Since the page table is closely related to the
+ * NuttX base address in this case, we can convert the page table base address
+ * to the base address of the section containing both.
+ */
+
+#ifdef CONFIG_ARCH_LOWVECTORS
+ .macro mksection, section, pgtable
+ bic \section, \pgtable, #0x000ff000
+ .endm
+#endif
+
+/* This macro will modify r0, r1, r2 and r14 */
+
+#ifdef CONFIG_DEBUG
+ .macro showprogress, code
+ mov r0, #\code
+ bl up_lowputc
+ .endm
+#else
+ .macro showprogress, code
+ .endm
+#endif
+
+/****************************************************************************
+ * Name: __start
+ ****************************************************************************/
+
+/* We assume the bootloader has already initialized most of the h/w for us
+ * and that only leaves us having to do some os specific things below.
+ */
+ .text
+ .global __start
+ .type __start, #function
+__start:
+ /* Make sure that we are in SVC mode with all IRQs disabled */
+
+ mov r0, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT)
+ msr cpsr_c, r0
+
+ /* Initialize DRAM using a macro provided by board-specific logic */
+
+#ifdef CONFIG_SDRAM
+ config_sdram
+#endif
+ /* Clear the 16K level 1 page table */
+
+ ldr r4, .LCppgtable /* r4=phys. page table */
+#ifndef CONFIG_ARCH_ROMPGTABLE
+ mov r0, r4
+ mov r1, #0
+ add r2, r0, #PGTABLE_SIZE
+.Lpgtableclear:
+ str r1, [r0], #4
+ str r1, [r0], #4
+ str r1, [r0], #4
+ str r1, [r0], #4
+ teq r0, r2
+ bne .Lpgtableclear
+
+ /* Create identity mapping for first MB of the .text section to support
+ * this startup logic executing out of the physical address space. This
+ * identity mapping will be removed by .Lvstart (see below). Of course,
+ * we would only do this if the physical-virtual mapping is not already
+ * the identity mapping.
+ */
+
+#ifndef CONFIG_IDENTITY_TEXTMAP
+ mksection r0, r4 /* r0=phys. base section */
+ ldr r1, .LCmmuflags /* FLGS=MMU_MEMFLAGS */
+ add r3, r1, r0 /* r3=flags + base */
+ str r3, [r4, r0, lsr #18] /* identity mapping */
+#endif
+
+#ifdef CONFIG_PAGING
+
+ /* Map the read-only .text region in place. This must be done
+ * before the MMU is enabled and the virtual addressing takes
+ * effect. First populate the L1 table for the locked and paged
+ * text regions.
+ *
+ * We could probably make the the pg_l1span and pg_l2map macros into
+ * call-able subroutines, but we would have to be carefully during
+ * this phase while we are operating in a physical address space.
+ *
+ * NOTE: That the value of r5 (L1 table base address) must be
+ * preserved through the following.
+ */
+
+ adr r0, .Ltxtspan
+ ldmia r0, {r0, r1, r2, r3, r5}
+ pg_l1span r0, r1, r2, r3, r5, r6
+
+ /* Then populate the L2 table for the locked text region only. */
+
+ adr r0, .Ltxtmap
+ ldmia r0, {r0, r1, r2, r3}
+ pg_l2map r0, r1, r2, r3, r5
+
+ /* Make sure that the page table is itself mapped and and read/write-able.
+ * First, populate the L1 table:
+ */
+
+ adr r0, .Lptabspan
+ ldmia r0, {r0, r1, r2, r3, r5}
+ pg_l1span r0, r1, r2, r3, r5, r6
+
+ /* Then populate the L2 table. */
+
+ adr r0, .Lptabmap
+ ldmia r0, {r0, r1, r2, r3}
+ pg_l2map r0, r1, r2, r3, r5
+
+#else /* CONFIG_PAGING */
+
+ /* Create a virtual single section mapping for the first MB of the .text
+ * address space. Now, we have the first 1MB mapping to both phyical and
+ * virtual addresses. The rest of the .text mapping will be completed in
+ * .Lvstart once we have moved the physical mapping out of the way.
+ *
+ * Here we expect to have:
+ * r4 = Address of the base of the L1 table
+ */
+
+ ldr r2, .LCvpgtable /* r2=virt. page table */
+ mksection r0, r2 /* r0=virt. base section */
+ str r3, [r4, r0, lsr #18] /* identity mapping */
+
+ /* NOTE: No .data/.bss access should be attempted. This temporary mapping
+ * can only be assumed to cover the initial .text region.
+ */
+
+#endif /* CONFIG_PAGING */
+#endif /* CONFIG_ARCH_ROMPGTABLE */
+
+ /* The following logic will set up the ARM920/ARM926 for normal operation.
+ *
+ * Here we expect to have:
+ * r4 = Address of the base of the L1 table
+ */
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c7 /* Invalidate I,D caches */
+ mcr p15, 0, r0, c7, c10, 4 /* Drain write buffer */
+ mcr p15, 0, r0, c8, c7 /* Invalidate I,D TLBs */
+ mcr p15, 0, r4, c2, c0 /* Load page table pointer */
+
+#ifdef CPU_DCACHE_WRITETHROUGH
+ mov r0, #4 /* Disable write-back on caches explicitly */
+ mcr p15, 7, r0, c15, c0, 0
+#endif
+
+ /* Enable the MMU and caches
+ * lr = Resume at .Lvstart with the MMU enabled
+ */
+
+ ldr lr, .LCvstart /* Abs. virtual address */
+
+ mov r0, #0x1f /* Domains 0, 1 = client */
+ mcr p15, 0, r0, c3, c0 /* Load domain access register */
+ mrc p15, 0, r0, c1, c0 /* Get control register */
+
+ /* Clear bits (see arm.h)
+ *
+ * CR_R - ROM MMU protection
+ * CR_F - Implementation defined
+ * CR_Z - Implementation defined
+ *
+ * CR_A - Alignment abort enable
+ * CR_C - Dcache enable
+ * CR_W - Write buffer enable
+ *
+ * CR_I - Icache enable
+ */
+
+ bic r0, r0, #(CR_R|CR_F|CR_Z)
+ bic r0, r0, #(CR_A|CR_C|CR_W)
+ bic r0, r0, #(CR_I)
+
+ /* Set bits (see arm.h)
+ *
+ * CR_M - MMU enable
+ * CR_P - 32-bit exception handler
+ * CR_D - 32-bit data address range
+ */
+
+ orr r0, r0, #(CR_M|CR_P|CR_D)
+
+ /* In most architectures, vectors are relocated to 0xffff0000.
+ * -- but not all
+ *
+ * CR_S - System MMU protection
+ * CR_V - Vectors relocated to 0xffff0000
+ */
+
+#ifndef CONFIG_ARCH_LOWVECTORS
+ orr r0, r0, #(CR_S|CR_V)
+#else
+ orr r0, r0, #(CR_S)
+#endif
+ /* CR_RR - Round Robin cache replacement */
+
+#ifdef CPU_CACHE_ROUND_ROBIN
+ orr r0, r0, #(CR_RR)
+#endif
+ /* CR_C - Dcache enable */
+
+#ifndef CPU_DCACHE_DISABLE
+ orr r0, r0, #(CR_C)
+#endif
+ /* CR_C - Dcache enable */
+
+#ifndef CPU_ICACHE_DISABLE
+ orr r0, r0, #(CR_I)
+#endif
+ /* CR_A - Alignment abort enable */
+
+#ifdef ALIGNMENT_TRAP
+ orr r0, r0, #(CR_A)
+#endif
+ mcr p15, 0, r0, c1, c0, 0 /* write control reg */
+
+ /* Get TMP=2 Processor ID register */
+
+ mrc p15, 0, r1, c0, c0, 0 /* read id reg */
+ mov r1,r1 /* Null-avoiding nop */
+ mov r1,r1 /* Null-avoiding nop */
+
+ /* And "jump" to .Lvstart */
+
+ mov pc, lr
+
+/****************************************************************************
+ * PC_Relative Data
+ ****************************************************************************/
+
+ /* Most addresses are all virtual address */
+
+ .type .LCvstart, %object
+.LCvstart:
+ .long .Lvstart
+
+#ifndef CONFIG_ARCH_ROMPGTABLE
+ .type .LCmmuflags, %object
+.LCmmuflags:
+ .long MMU_MEMFLAGS /* MMU flags for memory sections */
+#endif
+
+ .type .LCppgtable, %object
+.LCppgtable:
+ .long PGTABLE_BASE_PADDR /* Physical start of page table */
+
+#ifndef CONFIG_ARCH_ROMPGTABLE
+ .type .LCvpgtable, %object
+.LCvpgtable:
+ .long PGTABLE_BASE_VADDR /* Virtual start of page table */
+#endif
+
+#ifdef CONFIG_PAGING
+
+.Ltxtspan:
+ .long PG_L1_TEXT_PADDR /* Physical address in the L1 table */
+ .long PG_L2_TEXT_PBASE /* Physical address of the start of the L2 page table */
+ .long PG_TEXT_NVPAGES /* Total (virtual) text pages to be mapped */
+ .long PG_L2_TEXT_NPAGE1 /* The number of text pages in the first page table */
+ .long MMU_L1_TEXTFLAGS /* L1 MMU flags to use */
+
+.Ltxtmap:
+ .long PG_L2_LOCKED_PADDR /* Physical address in the L2 table */
+ .long PG_LOCKED_PBASE /* Physical address of locked base memory */
+ .long CONFIG_PAGING_NLOCKED /* Number of pages in the locked region */
+ .long MMU_L2_TEXTFLAGS /* L2 MMU flags to use */
+
+.Lptabspan:
+ .long PG_L1_PGTABLE_PADDR /* Physical address in the L1 table */
+ .long PG_L2_PGTABLE_PBASE /* Physical address of the start of the L2 page table */
+ .long PG_PGTABLE_NPAGES /* Total mapped page table pages */
+ .long PG_L2_PGTABLE_NPAGE1 /* The number of text pages in the first page table */
+ .long MMU_L1_PGTABFLAGS /* L1 MMU flags to use */
+
+.Lptabmap:
+ .long PG_L2_PGTABLE_PADDR /* Physical address in the L2 table */
+ .long PGTABLE_BASE_PADDR /* Physical address of the page table memory */
+ .long PG_PGTABLE_NPAGES /* Total mapped page table pages */
+ .long MMU_L2_PGTABFLAGS /* L2 MMU flags to use */
+
+#endif /* CONFIG_PAGING */
+ .size __start, .-__start
+
+/****************************************************************************
+ * Name: .Lvstart
+ ***************************************************************************/
+
+/* The following is executed after the MMU has been enabled. This uses
+ * absolute addresses; this is not position independent.
+ */
+ .align 5
+ .local .Lvstart
+ .type .Lvstart, %function
+.Lvstart:
+
+ /* Remove the temporary mapping (if one was made). The following assumes
+ * that the total RAM size is > 1Mb and extends that initial mapping to
+ * cover additinal RAM sections.
+ */
+
+
+#ifndef CONFIG_ARCH_ROMPGTABLE
+#ifndef CONFIG_IDENTITY_TEXTMAP
+ ldr r4, .LCvpgtable /* r4=virtual page table */
+ ldr r1, .LCppgtable /* r1=phys. page table */
+ mksection r3, r1 /* r2=phys. base addr */
+ mov r0, #0 /* flags + base = 0 */
+ str r0, [r4, r3, lsr #18] /* Undo identity mapping */
+#endif
+
+#if defined(CONFIG_PAGING)
+ /* Populate the L1 table for the data region */
+
+ adr r0, .Ldataspan
+ ldmia r0, {r0, r1, r2, r3, r4}
+ pg_l1span r0, r1, r2, r3, r4, r5
+
+ /* Populate the L2 table for the data region */
+
+ adr r0, .Ldatamap
+ ldmia r0, {r0, r1, r2, r3}
+ pg_l2map r0, r1, r2, r3, r4
+
+#elif defined(CONFIG_BOOT_RUNFROMFLASH)
+# error "Logic not implemented"
+#else
+ /* Now setup the pagetables for our normal SDRAM mappings mapped region.
+ * We round NUTTX_START_VADDR down to the nearest megabyte boundary.
+ */
+
+ ldr r1, .LCmmuflags /* FLGS=MMU_MEMFLAGS */
+ add r3, r3, r1 /* r3=flags + base */
+
+ add r0, r4, #(NUTTX_START_VADDR & 0xff000000) >> 18
+ bic r2, r3, #0x00f00000
+ str r2, [r0]
+
+ add r0, r0, #(NUTTX_START_VADDR & 0x00f00000) >> 18
+ str r3, [r0], #4
+
+ /* Now map the remaining RX_NSECTIONS-1 sections of the executable
+ * memory region.
+ */
+
+ .rept RX_NSECTIONS-1
+ add r3, r3, #SECTION_SIZE
+ str r3, [r0], #4
+ .endr
+
+ /* If we are executing from RAM with a fixed page configuration, then
+ * we can assume that the above contiguous mapping included all of the
+ * .text, .data, .bss, heap, etc. But if we are executing from FLASH,
+ * then the RAM area is probably in a separate physical address region
+ * and will require a separate mapping. Or, if we are supporting on-demand
+ * paging of the .text region, then the RAM-based .data/.bss/heap section
+ * will still probably be located in a separate (virtual) address region.
+ */
+
+#endif /* CONFIG_PAGING */
+#endif /* CONFIG_ARCH_ROMPGTABLE */
+
+ /* Zero BSS and set up the stack pointer */
+
+ adr r0, .Linitparms
+ ldmia r0, {r0, r1, sp}
+
+ /* Clear the frame pointer and .bss */
+
+ mov fp, #0
+
+.Lbssinit:
+ cmp r0, r1 /* Clear up to _bss_end_ */
+ strcc fp, [r0],#4
+ bcc .Lbssinit
+
+ /* If the .data section is in a separate, unitialized address space,
+ * then we will also need to copy the initial values of of the .data
+ * section from the .text region into that .data region. This would
+ * be the case if we are executing from FLASH and the .data section
+ * lies in a different physical address region OR if we are support
+ * on-demand paging and the .data section lies in a different virtual
+ * address region.
+ */
+
+#if defined(CONFIG_BOOT_RUNFROMFLASH) || defined(CONFIG_PAGING)
+ adr r3, .Ldatainit
+ ldmia r3, {r0, r1, r2}
+
+1: ldmia r0!, {r3 - r10}
+ stmia r1!, {r3 - r10}
+ cmp r1, r2
+ blt 1b
+#endif
+
+ /* Perform early C-level, platform-specific initialization */
+
+ bl up_boot
+
+ /* Finally branch to the OS entry point */
+
+ mov lr, #0
+ b os_start
+
+ /* Text-section constants:
+ *
+ * _sbss is the start of the BSS region (see ld.script)
+ * _ebss is the end of the BSS regsion (see ld.script)
+ *
+ * The idle task stack starts at the end of BSS and is of size
+ * CONFIG_IDLETHREAD_STACKSIZE. The heap continues from there until the
+ * end of memory. See g_heapbase below.
+ */
+
+.Linitparms:
+ .long _sbss
+ .long _ebss
+ .long _ebss+CONFIG_IDLETHREAD_STACKSIZE-4
+
+#ifdef CONFIG_PAGING
+
+.Ldataspan:
+ .long PG_L1_DATA_VADDR /* Virtual address in the L1 table */
+ .long PG_L2_DATA_PBASE /* Physical address of the start of the L2 page table */
+ .long PG_DATA_NPAGES /* Number of pages in the data region */
+ .long PG_L2_DATA_NPAGE1 /* The number of text pages in the first page table */
+ .long MMU_L1_DATAFLAGS /* L1 MMU flags to use */
+
+.Ldatamap:
+ .long PG_L2_DATA_VADDR /* Virtual address in the L2 table */
+ .long PG_DATA_PBASE /* Physical address of data memory */
+ .long PG_DATA_NPAGES /* Number of pages in the data region */
+ .long MMU_L2_DATAFLAGS /* L2 MMU flags to use */
+
+#endif /* CONFIG_PAGING */
+
+#if defined(CONFIG_BOOT_RUNFROMFLASH) || defined(CONFIG_PAGING)
+.Ldatainit:
+ .long _eronly /* Where .data defaults are stored in FLASH */
+ .long _sdata /* Where .data needs to reside in SDRAM */
+ .long _edata
+#endif
+ .size .Lvstart, .-.Lvstart
+
+ /* Data section variables */
+
+ /* This global variable is unsigned long g_heapbase and is
+ * exported from here only because of its coupling to .Linitparms
+ * above.
+ */
+
+ .data
+ .align 4
+ .globl g_heapbase
+ .type g_heapbase, object
+g_heapbase:
+ .long _ebss+CONFIG_IDLETHREAD_STACKSIZE
+ .size g_heapbase, .-g_heapbase
+ .end
+
diff --git a/nuttx/arch/arm/src/arm/up_initialstate.c b/nuttx/arch/arm/src/arm/up_initialstate.c
new file mode 100644
index 000000000..4711c9f44
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_initialstate.c
@@ -0,0 +1,146 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_initialstate.c
+ *
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <string.h>
+
+#include <nuttx/arch.h>
+
+#include "arm.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_initial_state
+ *
+ * Description:
+ * A new thread is being started and a new TCB
+ * has been created. This function is called to initialize
+ * the processor specific portions of the new TCB.
+ *
+ * This function must setup the intial architecture registers
+ * and/or stack so that execution will begin at tcb->start
+ * on the next context switch.
+ *
+ ****************************************************************************/
+
+void up_initial_state(_TCB *tcb)
+{
+ struct xcptcontext *xcp = &tcb->xcp;
+ uint32_t cpsr;
+
+ /* Initialize the initial exception register context structure */
+
+ memset(xcp, 0, sizeof(struct xcptcontext));
+
+ /* Save the initial stack pointer */
+
+ xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr;
+
+ /* Save the task entry point */
+
+ xcp->regs[REG_PC] = (uint32_t)tcb->start;
+
+ /* If this task is running PIC, then set the PIC base register to the
+ * address of the allocated D-Space region.
+ */
+
+#ifdef CONFIG_PIC
+ if (tcb->dspace != NULL)
+ {
+ /* Set the PIC base register (probably R10) to the address of the
+ * alloacated D-Space region.
+ */
+
+ xcp->regs[REG_PIC] = (uint32_t)tcb->dspace->region;
+ }
+#endif
+
+ /* Set supervisor- or user-mode, depending on how NuttX is configured and
+ * what kind of thread is being started. Disable FIQs in any event
+ */
+
+#ifdef CONFIG_NUTTX_KERNEL
+ if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL)
+ {
+ /* It is a kernel thread.. set supervisor mode */
+
+ cpsr = SVC_MODE | PSR_F_BIT;
+ }
+ else
+ {
+ /* It is a normal task or a pthread. Set user mode */
+
+ cpsr = USR_MODE | PSR_F_BIT;
+ }
+#else
+ /* If the kernel build is not selected, then all threads run in
+ * supervisor-mode.
+ */
+
+ cpsr = SVC_MODE | PSR_F_BIT;
+#endif
+
+ /* Enable or disable interrupts, based on user configuration */
+
+# ifdef CONFIG_SUPPRESS_INTERRUPTS
+ cpsr |= PSR_I_BIT;
+# endif
+
+ xcp->regs[REG_CPSR] = cpsr;
+}
+
diff --git a/nuttx/arch/arm/src/arm/up_nommuhead.S b/nuttx/arch/arm/src/arm/up_nommuhead.S
new file mode 100644
index 000000000..aac95b73a
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_nommuhead.S
@@ -0,0 +1,167 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_nommuhead.S
+ *
+ * Copyright (C) 2007, 2009-2010, 2012 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 "arm.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+/****************************************************************************
+ * Macros
+ ****************************************************************************/
+
+ /* This macro will modify r0, r1, r2 and r14 */
+
+#ifdef CONFIG_DEBUG
+ .macro showprogress, code
+ mov r0, #\code
+ bl up_lowputc
+ .endm
+#else
+ .macro showprogress, code
+ .endm
+#endif
+
+/****************************************************************************
+ * OS Entry Point
+ ****************************************************************************/
+
+/* We assume the bootloader has already initialized most of the h/w for
+ * us and that only leaves us having to do some os specific things
+ * below.
+ */
+ .text
+ .global __start
+ .type __start, #function
+__start:
+
+ /* First, setup initial processor mode */
+
+ mov r0, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT )
+ msr cpsr, r0
+
+ showprogress 'A'
+
+ /* Setup system stack (and get the BSS range) */
+
+ adr r0, LC0
+ ldmia r0, {r4, r5, sp}
+
+ /* Clear system BSS section */
+
+ mov r0, #0
+1: cmp r4, r5
+ strcc r0, [r4], #4
+ bcc 1b
+
+ showprogress 'B'
+
+ /* Copy system .data sections to new home in RAM. */
+
+#ifdef CONFIG_BOOT_RUNFROMFLASH
+
+ adr r3, LC2
+ ldmia r3, {r0, r1, r2}
+
+1: ldmia r0!, {r3 - r10}
+ stmia r1!, {r3 - r10}
+ cmp r1, r2
+ blt 1b
+
+#endif
+
+ /* Perform early serial initialization */
+
+ mov fp, #0
+#ifdef USE_EARLYSERIALINIT
+ bl up_earlyserialinit
+#endif
+
+#ifdef CONFIG_DEBUG
+ mov r0, #'C'
+ bl up_putc
+ mov r0, #'\n'
+ bl up_putc
+#endif
+ /* Initialize onboard LEDs */
+
+#ifdef CONFIG_ARCH_LEDS
+ bl up_ledinit
+#endif
+
+ /* Then jump to OS entry */
+
+ b os_start
+
+ /* Variables:
+ * _sbss is the start of the BSS region (see ld.script)
+ * _ebss is the end of the BSS regsion (see ld.script)
+ * The idle task stack starts at the end of BSS and is
+ * of size CONFIG_IDLETHREAD_STACKSIZE. The heap continues
+ * from there until the end of memory. See g_heapbase
+ * below.
+ */
+
+LC0: .long _sbss
+ .long _ebss
+ .long _ebss+CONFIG_IDLETHREAD_STACKSIZE-4
+
+#ifdef CONFIG_BOOT_RUNFROMFLASH
+LC2: .long _eronly /* Where .data defaults are stored in FLASH */
+ .long _sdata /* Where .data needs to reside in SDRAM */
+ .long _edata
+#endif
+ .size __start, .-__start
+
+ /* This global variable is unsigned long g_heapbase and is
+ * exported from here only because of its coupling to LCO
+ * above.
+ */
+
+ .data
+ .align 4
+ .globl g_heapbase
+ .type g_heapbase, object
+g_heapbase:
+ .long _ebss+CONFIG_IDLETHREAD_STACKSIZE
+ .size g_heapbase, .-g_heapbase
+
+ .end
+
diff --git a/nuttx/arch/arm/src/arm/up_pginitialize.c b/nuttx/arch/arm/src/arm/up_pginitialize.c
new file mode 100755
index 000000000..1aea95113
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_pginitialize.c
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_pginitialize.c
+ * Initialize the MMU for on-demand paging support.
+ *
+ * Copyright (C) 2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <nuttx/sched.h>
+#include <nuttx/page.h>
+
+#include "up_internal.h"
+
+#ifdef CONFIG_PAGING
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_pginitialize()
+ *
+ * Description:
+ * Initialize the MMU for on-demand paging support..
+ *
+ * Input Parameters:
+ * None.
+ *
+ * Returned Value:
+ * None. This function will crash if any errors are detected during MMU
+ * initialization
+ *
+ * Assumptions:
+ * - Called early in the platform initialization sequence so that no special
+ * concurrency protection is required.
+ *
+ ****************************************************************************/
+
+void up_pginitialize(void)
+{
+ /* None needed at present. This file is just retained in case the need
+ * arises in the future. Nothing calls up_pginitialize() now. If needed,
+ * if should be called early in up_boot.c to assure that all paging is
+ * ready.
+ */
+}
+
+#endif /* CONFIG_PAGING */
diff --git a/nuttx/arch/arm/src/arm/up_prefetchabort.c b/nuttx/arch/arm/src/arm/up_prefetchabort.c
new file mode 100644
index 000000000..ed3dd91d3
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_prefetchabort.c
@@ -0,0 +1,154 @@
+/****************************************************************************
+ * arch/arm/src/src/up_prefetchabort.c
+ *
+ * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <nuttx/irq.h>
+#ifdef CONFIG_PAGING
+# include <nuttx/page.h>
+#endif
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Debug ********************************************************************/
+
+/* Output debug info if stack dump is selected -- even if
+ * debug is not selected.
+ */
+
+#ifdef CONFIG_ARCH_STACKDUMP
+# undef lldbg
+# define lldbg lib_lowprintf
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_prefetchabort
+ *
+ * Description;
+ * This is the prefetch abort exception handler. The ARM prefetch abort
+ * exception occurs when a memory fault is detected during an an
+ * instruction fetch.
+ *
+ ****************************************************************************/
+
+void up_prefetchabort(uint32_t *regs)
+{
+#ifdef CONFIG_PAGING
+ uint32_t *savestate;
+
+ /* Save the saved processor context in current_regs where it can be accessed
+ * for register dumps and possibly context switching.
+ */
+
+ savestate = (uint32_t*)current_regs;
+#endif
+ current_regs = regs;
+
+#ifdef CONFIG_PAGING
+ /* Get the (virtual) address of instruction that caused the prefetch abort.
+ * When the exception occurred, this address was provided in the lr register
+ * and this value was saved in the context save area as the PC at the
+ * REG_R15 index.
+ *
+ * Check to see if this miss address is within the configured range of
+ * virtual addresses.
+ */
+
+ pglldbg("VADDR: %08x VBASE: %08x VEND: %08x\n",
+ regs[REG_PC], PG_PAGED_VBASE, PG_PAGED_VEND);
+
+ if (regs[REG_R15] >= PG_PAGED_VBASE && regs[REG_R15] < PG_PAGED_VEND)
+ {
+ /* Save the offending PC as the fault address in the TCB of the currently
+ * executing task. This value is, of course, already known in regs[REG_R15],
+ * but saving it in this location will allow common paging logic for both
+ * prefetch and data aborts.
+ */
+
+ FAR _TCB *tcb = (FAR _TCB *)g_readytorun.head;
+ tcb->xcp.far = regs[REG_R15];
+
+ /* Call pg_miss() to schedule the page fill. A consequences of this
+ * call are:
+ *
+ * (1) The currently executing task will be blocked and saved on
+ * on the g_waitingforfill task list.
+ * (2) An interrupt-level context switch will occur so that when
+ * this function returns, it will return to a different task,
+ * most likely the page fill worker thread.
+ * (3) The page fill worker task has been signalled and should
+ * execute immediately when we return from this exception.
+ */
+
+ pg_miss();
+
+ /* Restore the previous value of current_regs. NULL would indicate that
+ * we are no longer in an interrupt handler. It will be non-NULL if we
+ * are returning from a nested interrupt.
+ */
+
+ current_regs = savestate;
+ }
+ else
+#endif
+ {
+ lldbg("Prefetch abort. PC: %08x\n", regs[REG_PC]);
+ PANIC(OSERR_ERREXCEPTION);
+ }
+}
diff --git a/nuttx/arch/arm/src/arm/up_releasepending.c b/nuttx/arch/arm/src/arm/up_releasepending.c
new file mode 100755
index 000000000..dcad40159
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_releasepending.c
@@ -0,0 +1,132 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_releasepending.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sched.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_release_pending
+ *
+ * Description:
+ * Release and ready-to-run tasks that have
+ * collected in the pending task list. This can call a
+ * context switch if a new task is placed at the head of
+ * the ready to run list.
+ *
+ ****************************************************************************/
+
+void up_release_pending(void)
+{
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+
+ slldbg("From TCB=%p\n", rtcb);
+
+ /* Merge the g_pendingtasks list into the g_readytorun task list */
+
+ /* sched_lock(); */
+ if (sched_mergepending())
+ {
+ /* The currently active task has changed! We will need to
+ * switch contexts. First check if we are operating in
+ * interrupt context:
+ */
+
+ if (current_regs)
+ {
+ /* Yes, then we have to do things differently.
+ * Just copy the current_regs into the OLD rtcb.
+ */
+
+ up_savestate(rtcb->xcp.regs);
+
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+ slldbg("New Active Task TCB=%p\n", rtcb);
+
+ /* Then switch contexts */
+
+ up_restorestate(rtcb->xcp.regs);
+ }
+
+ /* Copy the exception context into the TCB of the task that
+ * was currently active. if up_saveusercontext returns a non-zero
+ * value, then this is really the previously running task
+ * restarting!
+ */
+
+ else if (!up_saveusercontext(rtcb->xcp.regs))
+ {
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+ slldbg("New Active Task TCB=%p\n", rtcb);
+
+ /* Then switch contexts */
+
+ up_fullcontextrestore(rtcb->xcp.regs);
+ }
+ }
+}
diff --git a/nuttx/arch/arm/src/arm/up_reprioritizertr.c b/nuttx/arch/arm/src/arm/up_reprioritizertr.c
new file mode 100755
index 000000000..38bce2a72
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_reprioritizertr.c
@@ -0,0 +1,187 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_reprioritizertr.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <stdbool.h>
+#include <sched.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_reprioritize_rtr
+ *
+ * Description:
+ * Called when the priority of a running or
+ * ready-to-run task changes and the reprioritization will
+ * cause a context switch. Two cases:
+ *
+ * 1) The priority of the currently running task drops and the next
+ * task in the ready to run list has priority.
+ * 2) An idle, ready to run task's priority has been raised above the
+ * the priority of the current, running task and it now has the
+ * priority.
+ *
+ * Inputs:
+ * tcb: The TCB of the task that has been reprioritized
+ * priority: The new task priority
+ *
+ ****************************************************************************/
+
+void up_reprioritize_rtr(_TCB *tcb, uint8_t priority)
+{
+ /* Verify that the caller is sane */
+
+ if (tcb->task_state < FIRST_READY_TO_RUN_STATE ||
+ tcb->task_state > LAST_READY_TO_RUN_STATE
+#if SCHED_PRIORITY_MIN > 0
+ || priority < SCHED_PRIORITY_MIN
+#endif
+#if SCHED_PRIORITY_MAX < UINT8_MAX
+ || priority > SCHED_PRIORITY_MAX
+#endif
+ )
+ {
+ PANIC(OSERR_BADREPRIORITIZESTATE);
+ }
+ else
+ {
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+ bool switch_needed;
+
+ slldbg("TCB=%p PRI=%d\n", tcb, priority);
+
+ /* Remove the tcb task from the ready-to-run list.
+ * sched_removereadytorun will return true if we just
+ * remove the head of the ready to run list.
+ */
+
+ switch_needed = sched_removereadytorun(tcb);
+
+ /* Setup up the new task priority */
+
+ tcb->sched_priority = (uint8_t)priority;
+
+ /* Return the task to the specified blocked task list.
+ * sched_addreadytorun will return true if the task was
+ * added to the new list. We will need to perform a context
+ * switch only if the EXCLUSIVE or of the two calls is non-zero
+ * (i.e., one and only one the calls changes the head of the
+ * ready-to-run list).
+ */
+
+ switch_needed ^= sched_addreadytorun(tcb);
+
+ /* Now, perform the context switch if one is needed */
+
+ if (switch_needed)
+ {
+ /* If we are going to do a context switch, then now is the right
+ * time to add any pending tasks back into the ready-to-run list.
+ * task list now
+ */
+
+ if (g_pendingtasks.head)
+ {
+ sched_mergepending();
+ }
+
+ /* Are we in an interrupt handler? */
+
+ if (current_regs)
+ {
+ /* Yes, then we have to do things differently.
+ * Just copy the current_regs into the OLD rtcb.
+ */
+
+ up_savestate(rtcb->xcp.regs);
+
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+ slldbg("New Active Task TCB=%p\n", rtcb);
+
+ /* Then switch contexts */
+
+ up_restorestate(rtcb->xcp.regs);
+ }
+
+ /* Copy the exception context into the TCB at the (old) head of the
+ * g_readytorun Task list. if up_saveusercontext returns a non-zero
+ * value, then this is really the previously running task restarting!
+ */
+
+ else if (!up_saveusercontext(rtcb->xcp.regs))
+ {
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+ slldbg("New Active Task TCB=%p\n", rtcb);
+
+ /* Then switch contexts */
+
+ up_fullcontextrestore(rtcb->xcp.regs);
+ }
+ }
+ }
+}
diff --git a/nuttx/arch/arm/src/arm/up_saveusercontext.S b/nuttx/arch/arm/src/arm/up_saveusercontext.S
new file mode 100644
index 000000000..8d154d187
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_saveusercontext.S
@@ -0,0 +1,119 @@
+/**************************************************************************
+ * arch/arm/src/arm/up_saveusercontext.S
+ *
+ * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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/irq.h>
+#include "up_internal.h"
+
+/**************************************************************************
+ * Private Definitions
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Types
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Function Prototypes
+ **************************************************************************/
+
+/**************************************************************************
+ * Global Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Public Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Name: up_saveusercontext
+ **************************************************************************/
+
+ .text
+ .globl up_saveusercontext
+ .type up_saveusercontext, function
+up_saveusercontext:
+ /* On entry, a1 (r0) holds address of struct xcptcontext.
+ * Offset to the user region.
+ */
+
+ /* Make sure that the return value will be non-zero (the
+ * value of the other volatile registers don't matter --
+ * r1-r3, ip). This function is called throught the
+ * noraml C calling conventions and the values of these
+ * registers cannot be assumed at the point of setjmp
+ * return.
+ */
+
+ mov ip, #1
+ str ip, [r0, #(4*REG_R0)]
+
+ /* Save the volatile registers (plus r12 which really
+ * doesn't need to be saved)
+ */
+
+ add r1, r0, #(4*REG_R4)
+ stmia r1, {r4-r14}
+
+ /* Save the current cpsr */
+
+ mrs r2, cpsr /* R3 = CPSR value */
+ add r1, r0, #(4*REG_CPSR)
+ str r2, [r1]
+
+ /* Finally save the return address as the PC so that we
+ * return to the exit from this function.
+ */
+
+ add r1, r0, #(4*REG_PC)
+ str lr, [r1]
+
+ /* Return 0 */
+
+ mov r0, #0 /* Return value == 0 */
+ mov pc, lr /* Return */
+ .size up_saveusercontext, . - up_saveusercontext
+
diff --git a/nuttx/arch/arm/src/arm/up_schedulesigaction.c b/nuttx/arch/arm/src/arm/up_schedulesigaction.c
new file mode 100644
index 000000000..0dfb6e540
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_schedulesigaction.c
@@ -0,0 +1,204 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_schedulesigaction.c
+ *
+ * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sched.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+
+#include "arm.h"
+#include "os_internal.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+#ifndef CONFIG_DISABLE_SIGNALS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_schedule_sigaction
+ *
+ * Description:
+ * This function is called by the OS when one or more
+ * signal handling actions have been queued for execution.
+ * The architecture specific code must configure things so
+ * that the 'igdeliver' callback is executed on the thread
+ * specified by 'tcb' as soon as possible.
+ *
+ * This function may be called from interrupt handling logic.
+ *
+ * This operation should not cause the task to be unblocked
+ * nor should it cause any immediate execution of sigdeliver.
+ * Typically, a few cases need to be considered:
+ *
+ * (1) This function may be called from an interrupt handler
+ * During interrupt processing, all xcptcontext structures
+ * should be valid for all tasks. That structure should
+ * be modified to invoke sigdeliver() either on return
+ * from (this) interrupt or on some subsequent context
+ * switch to the recipient task.
+ * (2) If not in an interrupt handler and the tcb is NOT
+ * the currently executing task, then again just modify
+ * the saved xcptcontext structure for the recipient
+ * task so it will invoke sigdeliver when that task is
+ * later resumed.
+ * (3) If not in an interrupt handler and the tcb IS the
+ * currently executing task -- just call the signal
+ * handler now.
+ *
+ ****************************************************************************/
+
+void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver)
+{
+ /* Refuse to handle nested signal actions */
+
+ sdbg("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver);
+
+ if (!tcb->xcp.sigdeliver)
+ {
+ irqstate_t flags;
+
+ /* Make sure that interrupts are disabled */
+
+ flags = irqsave();
+
+ /* First, handle some special cases when the signal is
+ * being delivered to the currently executing task.
+ */
+
+ sdbg("rtcb=0x%p current_regs=0x%p\n", g_readytorun.head, current_regs);
+
+ if (tcb == (_TCB*)g_readytorun.head)
+ {
+ /* CASE 1: We are not in an interrupt handler and
+ * a task is signalling itself for some reason.
+ */
+
+ if (!current_regs)
+ {
+ /* In this case just deliver the signal now. */
+
+ sigdeliver(tcb);
+ }
+
+ /* CASE 2: We are in an interrupt handler AND the
+ * interrupted task is the same as the one that
+ * must receive the signal, then we will have to modify
+ * the return state as well as the state in the TCB.
+ *
+ * Hmmm... there looks like a latent bug here: The following
+ * logic would fail in the strange case where we are in an
+ * interrupt handler, the thread is signalling itself, but
+ * a context switch to another task has occurred so that
+ * current_regs does not refer to the thread at g_readytorun.head!
+ */
+
+ else
+ {
+ /* Save the return lr and cpsr and one scratch register
+ * These will be restored by the signal trampoline after
+ * the signals have been delivered.
+ */
+
+ tcb->xcp.sigdeliver = sigdeliver;
+ tcb->xcp.saved_pc = current_regs[REG_PC];
+ tcb->xcp.saved_cpsr = current_regs[REG_CPSR];
+
+ /* Then set up to vector to the trampoline with interrupts
+ * disabled
+ */
+
+ current_regs[REG_PC] = (uint32_t)up_sigdeliver;
+ current_regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
+
+ /* And make sure that the saved context in the TCB
+ * is the same as the interrupt return context.
+ */
+
+ up_savestate(tcb->xcp.regs);
+ }
+ }
+
+ /* Otherwise, we are (1) signaling a task is not running
+ * from an interrupt handler or (2) we are not in an
+ * interrupt handler and the running task is signalling
+ * some non-running task.
+ */
+
+ else
+ {
+ /* Save the return lr and cpsr and one scratch register
+ * These will be restored by the signal trampoline after
+ * the signals have been delivered.
+ */
+
+ tcb->xcp.sigdeliver = sigdeliver;
+ tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
+ tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR];
+
+ /* Then set up to vector to the trampoline with interrupts
+ * disabled
+ */
+
+ tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
+ tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
+ }
+
+ irqrestore(flags);
+ }
+}
+
+#endif /* !CONFIG_DISABLE_SIGNALS */
diff --git a/nuttx/arch/arm/src/arm/up_sigdeliver.c b/nuttx/arch/arm/src/arm/up_sigdeliver.c
new file mode 100644
index 000000000..f92f85e7e
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_sigdeliver.c
@@ -0,0 +1,139 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_sigdeliver.c
+ *
+ * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sched.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+#ifndef CONFIG_DISABLE_SIGNALS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_sigdeliver
+ *
+ * Description:
+ * This is the a signal handling trampoline. When a signal action was
+ * posted. The task context was mucked with and forced to branch to this
+ * location with interrupts disabled.
+ *
+ ****************************************************************************/
+
+void up_sigdeliver(void)
+{
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+ uint32_t regs[XCPTCONTEXT_REGS];
+ sig_deliver_t sigdeliver;
+
+ /* Save the errno. This must be preserved throughout the signal handling
+ * so that the user code final gets the correct errno value (probably
+ * EINTR).
+ */
+
+ int saved_errno = rtcb->pterrno;
+
+ up_ledon(LED_SIGNAL);
+
+ sdbg("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
+ rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
+ ASSERT(rtcb->xcp.sigdeliver != NULL);
+
+ /* Save the real return state on the stack. */
+
+ up_copystate(regs, rtcb->xcp.regs);
+ regs[REG_PC] = rtcb->xcp.saved_pc;
+ regs[REG_CPSR] = rtcb->xcp.saved_cpsr;
+
+ /* Get a local copy of the sigdeliver function pointer. we do this so that
+ * we can nullify the sigdeliver function pointer in the TCB and accept
+ * more signal deliveries while processing the current pending signals.
+ */
+
+ sigdeliver = rtcb->xcp.sigdeliver;
+ rtcb->xcp.sigdeliver = NULL;
+
+ /* Then restore the task interrupt state */
+
+ irqrestore(regs[REG_CPSR]);
+
+ /* Deliver the signals */
+
+ sigdeliver(rtcb);
+
+ /* Output any debug messages BEFORE restoring errno (because they may
+ * alter errno), then disable interrupts again and restore the original
+ * errno that is needed by the user logic (it is probably EINTR).
+ */
+
+ sdbg("Resuming\n");
+ (void)irqsave();
+ rtcb->pterrno = saved_errno;
+
+ /* Then restore the correct state for this thread of execution. */
+
+ up_ledoff(LED_SIGNAL);
+ up_fullcontextrestore(regs);
+}
+
+#endif /* !CONFIG_DISABLE_SIGNALS */
+
diff --git a/nuttx/arch/arm/src/arm/up_syscall.c b/nuttx/arch/arm/src/arm/up_syscall.c
new file mode 100644
index 000000000..f331a1314
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_syscall.c
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_syscall.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include "up_arch.h"
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Output debug info if stack dump is selected -- even if
+ * debug is not selected.
+ */
+
+#ifdef CONFIG_ARCH_STACKDUMP
+# undef lldbg
+# define lldbg lib_lowprintf
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * vectors
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_syscall
+ *
+ * Description:
+ * SWI interrupts will vection here with insn=the SWI
+ * instruction and xcp=the interrupt context
+ *
+ * The handler may get the SWI number be de-referencing
+ * the return address saved in the xcp and decoding
+ * the SWI instruction
+ *
+ ****************************************************************************/
+
+void up_syscall(uint32_t *regs)
+{
+ lldbg("Syscall from 0x%x\n", regs[REG_PC]);
+ current_regs = regs;
+ PANIC(OSERR_ERREXCEPTION);
+}
diff --git a/nuttx/arch/arm/src/arm/up_unblocktask.c b/nuttx/arch/arm/src/arm/up_unblocktask.c
new file mode 100755
index 000000000..73e292561
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_unblocktask.c
@@ -0,0 +1,159 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_unblocktask.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sched.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "clock_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_unblock_task
+ *
+ * Description:
+ * A task is currently in an inactive task list
+ * but has been prepped to execute. Move the TCB to the
+ * ready-to-run list, restore its context, and start execution.
+ *
+ * Inputs:
+ * tcb: Refers to the tcb to be unblocked. This tcb is
+ * in one of the waiting tasks lists. It must be moved to
+ * the ready-to-run list and, if it is the highest priority
+ * ready to run taks, executed.
+ *
+ ****************************************************************************/
+
+void up_unblock_task(_TCB *tcb)
+{
+ /* Verify that the context switch can be performed */
+
+ if ((tcb->task_state < FIRST_BLOCKED_STATE) ||
+ (tcb->task_state > LAST_BLOCKED_STATE))
+ {
+ PANIC(OSERR_BADUNBLOCKSTATE);
+ }
+ else
+ {
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+
+ /* Remove the task from the blocked task list */
+
+ sched_removeblocked(tcb);
+
+ /* Reset its timeslice. This is only meaningful for round
+ * robin tasks but it doesn't here to do it for everything
+ */
+
+#if CONFIG_RR_INTERVAL > 0
+ tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK;
+#endif
+
+ /* Add the task in the correct location in the prioritized
+ * g_readytorun task list
+ */
+
+ if (sched_addreadytorun(tcb))
+ {
+ /* The currently active task has changed! We need to do
+ * a context switch to the new task.
+ *
+ * Are we in an interrupt handler?
+ */
+
+ if (current_regs)
+ {
+ /* Yes, then we have to do things differently.
+ * Just copy the current_regs into the OLD rtcb.
+ */
+
+ up_savestate(rtcb->xcp.regs);
+
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+
+ /* Then switch contexts */
+
+ up_restorestate(rtcb->xcp.regs);
+ }
+
+ /* We are not in an interrupt handler. Copy the user C context
+ * into the TCB of the task that was previously active. if
+ * up_saveusercontext returns a non-zero value, then this is really the
+ * previously running task restarting!
+ */
+
+ else if (!up_saveusercontext(rtcb->xcp.regs))
+ {
+ /* Restore the exception context of the new task that is ready to
+ * run (probably tcb). This is the new rtcb at the head of the
+ * g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+
+ /* Then switch contexts */
+
+ up_fullcontextrestore(rtcb->xcp.regs);
+ }
+ }
+ }
+}
diff --git a/nuttx/arch/arm/src/arm/up_undefinedinsn.c b/nuttx/arch/arm/src/arm/up_undefinedinsn.c
new file mode 100644
index 000000000..4c50991b0
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_undefinedinsn.c
@@ -0,0 +1,81 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_undefinedinsn.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Output debug info if stack dump is selected -- even if
+ * debug is not selected.
+ */
+
+#ifdef CONFIG_ARCH_STACKDUMP
+# undef lldbg
+# define lldbg lib_lowprintf
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_undefinedinsn
+ ****************************************************************************/
+
+void up_undefinedinsn(uint32_t *regs)
+{
+ lldbg("Undefined instruction at 0x%x\n", regs[REG_PC]);
+ current_regs = regs;
+ PANIC(OSERR_UNDEFINEDINSN);
+}
diff --git a/nuttx/arch/arm/src/arm/up_va2pte.c b/nuttx/arch/arm/src/arm/up_va2pte.c
new file mode 100755
index 000000000..5f92ad821
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_va2pte.c
@@ -0,0 +1,121 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_va2pte.c
+ * Utility to map a virtual address to a L2 page table entry.
+ *
+ * Copyright (C) 2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <nuttx/sched.h>
+#include <nuttx/page.h>
+
+#include "chip.h"
+#include "pg_macros.h"
+#include "up_internal.h"
+
+#ifdef CONFIG_PAGING
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_va2pte()
+ *
+ * Description:
+ * Convert a virtual address within the paged text region into a pointer to
+ * the corresponding page table entry.
+ *
+ * Input Parameters:
+ * vaddr - The virtual address within the paged text region.
+ *
+ * Returned Value:
+ * A pointer to the corresponding page table entry.
+ *
+ * Assumptions:
+ * - This function is called from the normal tasking context (but with
+ * interrupts disabled). The implementation must take whatever actions
+ * are necessary to assure that the operation is safe within this
+ * context.
+ *
+ ****************************************************************************/
+
+uint32_t *up_va2pte(uintptr_t vaddr)
+{
+ uint32_t L1;
+ uint32_t *L2;
+ unsigned int ndx;
+
+ /* The virtual address is expected to lie in the paged text region */
+
+ DEBUGASSERT(vaddr >= PG_PAGED_VBASE && vaddr < PG_PAGED_VEND);
+
+ /* Get the L1 table entry associated with this virtual address */
+
+ L1 = *(uint32_t*)PG_POOL_VA2L1VADDR(vaddr);
+
+ /* Get the address of the L2 page table from the L1 entry */
+
+ L2 = (uint32_t*)PG_POOL_L12VPTABLE(L1);
+
+ /* Get the index into the L2 page table. Each L1 entry maps
+ * 256 x 4Kb or 1024 x 1Kb pages.
+ */
+
+ ndx = (vaddr & 0x000fffff) >> PAGESHIFT;
+
+ /* Return true if this virtual address is mapped. */
+
+ return &L2[ndx];
+}
+
+#endif /* CONFIG_PAGING */
diff --git a/nuttx/arch/arm/src/arm/up_vectoraddrexcptn.S b/nuttx/arch/arm/src/arm/up_vectoraddrexcptn.S
new file mode 100644
index 000000000..e034c394f
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_vectoraddrexcptn.S
@@ -0,0 +1,83 @@
+/************************************************************************************
+ * arch/arm/src/src/up_vectoraddrexceptn.S
+ *
+ * Copyright (C) 2008-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <nuttx/irq.h>
+#include "up_arch.h"
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Global Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Assembly Macros
+ ************************************************************************************/
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+ .text
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+ .text
+
+/************************************************************************************
+ * Name: up_vectoraddrexcption
+ *
+ * Description:
+ * Shouldn't happen. This exception handler is in a separate file from other
+ * vector handlers because some processors (e.g., lpc2148) do not support the
+ * the Address Exception vector.
+ *
+ ************************************************************************************/
+
+ .globl up_vectoraddrexcptn
+ .type up_vectoraddrexcptn, %function
+up_vectoraddrexcptn:
+ b up_vectoraddrexcptn
+ .size up_vectoraddrexcptn, . - up_vectoraddrexcptn
+ .end
diff --git a/nuttx/arch/arm/src/arm/up_vectors.S b/nuttx/arch/arm/src/arm/up_vectors.S
new file mode 100644
index 000000000..00c5d52b0
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_vectors.S
@@ -0,0 +1,446 @@
+/************************************************************************************
+ * arch/arm/src/arm/up_vectors.S
+ *
+ * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <nuttx/irq.h>
+
+#include "arm.h"
+#include "up_arch.h"
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Global Data
+ ************************************************************************************/
+
+ .data
+g_irqtmp:
+ .word 0 /* Saved lr */
+ .word 0 /* Saved spsr */
+g_undeftmp:
+ .word 0 /* Saved lr */
+ .word 0 /* Saved spsr */
+g_aborttmp:
+ .word 0 /* Saved lr */
+ .word 0 /* Saved spsr */
+
+/************************************************************************************
+ * Assembly Macros
+ ************************************************************************************/
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+ .text
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+ .text
+
+/************************************************************************************
+ * Name: up_vectorirq
+ *
+ * Description:
+ * Interrupt excetpion. Entered in IRQ mode with spsr = SVC CPSR, lr = SVC PC
+ *
+ ************************************************************************************/
+
+ .globl up_vectorirq
+ .type up_vectorirq, %function
+up_vectorirq:
+ /* On entry, we are in IRQ mode. We are free to use
+ * the IRQ mode r13 and r14.
+ */
+
+ ldr r13, .Lirqtmp
+ sub lr, lr, #4
+ str lr, [r13] @ save lr_IRQ
+ mrs lr, spsr
+ str lr, [r13, #4] @ save spsr_IRQ
+
+ /* Then switch back to SVC mode */
+
+ bic lr, lr, #MODE_MASK /* Keep F and T bits */
+ orr lr, lr, #(SVC_MODE | PSR_I_BIT)
+ msr cpsr_c, lr /* Switch to SVC mode */
+
+ /* Create a context structure. First set aside a stack frame
+ * and store r0-r12 into the frame.
+ */
+
+ sub sp, sp, #XCPTCONTEXT_SIZE
+ stmia sp, {r0-r12} /* Save the SVC mode regs */
+
+ /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
+
+ add r1, sp, #XCPTCONTEXT_SIZE
+ mov r2, r14
+
+ /* Get the values for r15(pc) and CPSR in r3 and r4 */
+
+ ldr r0, .Lirqtmp /* Points to temp storage */
+ ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
+
+ add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
+ stmia r0, {r1-r4}
+
+ /* Then call the IRQ handler with interrupts disabled. */
+
+ mov fp, #0 /* Init frame pointer */
+ mov r0, sp /* Get r0=xcp */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ ldr sp, .Lirqstackbase /* SP = interrupt stack base */
+ str r0, [sp] /* Save the user stack pointer */
+ bl up_decodeirq /* Call the handler */
+ ldr sp, [sp] /* Restore the user stack pointer */
+#else
+ bl up_decodeirq /* Call the handler */
+#endif
+
+ /* Restore the CPSR, SVC modr registers and return */
+.Lnoirqset:
+ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
+ msr spsr, r0
+ ldmia sp, {r0-r15}^ /* Return */
+
+.Lirqtmp:
+ .word g_irqtmp
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+.Lirqstackbase:
+ .word up_stackbase
+#endif
+ .size up_vectorirq, . - up_vectorirq
+ .align 5
+
+/************************************************************************************
+ * Function: up_vectorswi
+ *
+ * Description:
+ * SWI interrupt. We enter the SWI in SVC mode.
+ *
+ ************************************************************************************/
+
+ .globl up_vectorswi
+ .type up_vectorswi, %function
+up_vectorswi:
+
+ /* Create a context structure. First set aside a stack frame
+ * and store r0-r12 into the frame.
+ */
+
+ sub sp, sp, #XCPTCONTEXT_SIZE
+ stmia sp, {r0-r12} /* Save the SVC mode regs */
+
+ /* Get the correct values of r13(sp), r14(lr), r15(pc)
+ * and CPSR in r1-r4 */
+
+ add r1, sp, #XCPTCONTEXT_SIZE
+ mov r2, r14 /* R14 is altered on return from SWI */
+ mov r3, r14 /* Save r14 as the PC as well */
+ mrs r4, spsr /* Get the saved CPSR */
+
+ add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
+ stmia r0, {r1-r4}
+
+ /* Then call the SWI handler with interrupts disabled.
+ * void up_syscall(struct xcptcontext *xcp)
+ */
+
+ mov fp, #0 /* Init frame pointer */
+ mov r0, sp /* Get r0=xcp */
+ bl up_syscall /* Call the handler */
+
+ /* Restore the CPSR, SVC modr registers and return */
+
+ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
+ msr spsr, r0
+ ldmia sp, {r0-r15}^ /* Return */
+ .size up_vectorswi, . - up_vectorswi
+
+ .align 5
+
+/************************************************************************************
+ * Name: up_vectordata
+ *
+ * Description:
+ * This is the data abort exception dispatcher. The ARM data abort exception occurs
+ * when a memory fault is detected during a data transfer. This handler saves the
+ * current processor state and gives control to data abort handler. This function
+ * is entered in ABORT mode with spsr = SVC CPSR, lr = SVC PC
+ *
+ ************************************************************************************/
+
+ .globl up_vectordata
+ .type up_vectordata, %function
+up_vectordata:
+ /* On entry we are free to use the ABORT mode registers
+ * r13 and r14
+ */
+
+ ldr r13, .Ldaborttmp /* Points to temp storage */
+ sub lr, lr, #8 /* Fixup return */
+ str lr, [r13] /* Save in temp storage */
+ mrs lr, spsr /* Get SPSR */
+ str lr, [r13, #4] /* Save in temp storage */
+
+ /* Then switch back to SVC mode */
+
+ bic lr, lr, #MODE_MASK /* Keep F and T bits */
+ orr lr, lr, #(SVC_MODE | PSR_I_BIT)
+ msr cpsr_c, lr /* Switch to SVC mode */
+
+ /* Create a context structure. First set aside a stack frame
+ * and store r0-r12 into the frame.
+ */
+
+ sub sp, sp, #XCPTCONTEXT_SIZE
+ stmia sp, {r0-r12} /* Save the SVC mode regs */
+
+ /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
+
+ add r1, sp, #XCPTCONTEXT_SIZE
+ mov r2, r14
+
+ /* Get the values for r15(pc) and CPSR in r3 and r4 */
+
+ ldr r0, .Ldaborttmp /* Points to temp storage */
+ ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
+
+ add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
+ stmia r0, {r1-r4}
+
+ /* Then call the data abort handler with interrupts disabled.
+ * void up_dataabort(struct xcptcontext *xcp)
+ */
+
+ mov fp, #0 /* Init frame pointer */
+ mov r0, sp /* Get r0=xcp */
+#ifdef CONFIG_PAGING
+ mrc p15, 0, r2, c5, c0, 0 /* Get r2=FSR */
+ mrc p15, 0, r1, c6, c0, 0 /* Get R1=FAR */
+#endif
+ bl up_dataabort /* Call the handler */
+
+ /* Restore the CPSR, SVC modr registers and return */
+
+ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
+ msr spsr_cxsf, r0
+ ldmia sp, {r0-r15}^ /* Return */
+
+.Ldaborttmp:
+ .word g_aborttmp
+ .size up_vectordata, . - up_vectordata
+
+ .align 5
+
+/************************************************************************************
+ * Name: up_vectorprefetch
+ *
+ * Description:
+ * This is the prefetch abort exception dispatcher. The ARM prefetch abort exception
+ * occurs when a memory fault is detected during an an instruction fetch. This
+ * handler saves the current processor state and gives control to prefetch abort
+ * handler. This function is entered in ABT mode with spsr = SVC CPSR, lr = SVC PC.
+ *
+ ************************************************************************************/
+
+ .globl up_vectorprefetch
+ .type up_vectorprefetch, %function
+up_vectorprefetch:
+ /* On entry we are free to use the ABORT mode registers
+ * r13 and r14
+ */
+
+ ldr r13, .Lpaborttmp /* Points to temp storage */
+ sub lr, lr, #4 /* Fixup return */
+ str lr, [r13] /* Save in temp storage */
+ mrs lr, spsr /* Get SPSR */
+ str lr, [r13, #4] /* Save in temp storage */
+
+ /* Then switch back to SVC mode */
+
+ bic lr, lr, #MODE_MASK /* Keep F and T bits */
+ orr lr, lr, #(SVC_MODE | PSR_I_BIT)
+ msr cpsr_c, lr /* Switch to SVC mode */
+
+ /* Create a context structure. First set aside a stack frame
+ * and store r0-r12 into the frame.
+ */
+
+ sub sp, sp, #XCPTCONTEXT_SIZE
+ stmia sp, {r0-r12} /* Save the SVC mode regs */
+
+ /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
+
+ add r1, sp, #XCPTCONTEXT_SIZE
+ mov r2, r14
+
+ /* Get the values for r15(pc) and CPSR in r3 and r4 */
+
+ ldr r0, .Lpaborttmp /* Points to temp storage */
+ ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
+
+ add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
+ stmia r0, {r1-r4}
+
+ /* Then call the prefetch abort handler with interrupts disabled.
+ * void up_prefetchabort(struct xcptcontext *xcp)
+ */
+
+ mov fp, #0 /* Init frame pointer */
+ mov r0, sp /* Get r0=xcp */
+ bl up_prefetchabort /* Call the handler */
+
+ /* Restore the CPSR, SVC modr registers and return */
+
+ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
+ msr spsr_cxsf, r0
+ ldmia sp, {r0-r15}^ /* Return */
+
+.Lpaborttmp:
+ .word g_aborttmp
+ .size up_vectorprefetch, . - up_vectorprefetch
+
+ .align 5
+
+/************************************************************************************
+ * Name: up_vectorundefinsn
+ *
+ * Description:
+ * Undefined instruction entry exception. Entered in UND mode, spsr = SVC CPSR,
+ * lr = SVC PC
+ *
+ ************************************************************************************/
+
+ .globl up_vectorundefinsn
+ .type up_vectorundefinsn, %function
+up_vectorundefinsn:
+ /* On entry we are free to use the UND mode registers
+ * r13 and r14
+ */
+
+ ldr r13, .Lundeftmp /* Points to temp storage */
+ str lr, [r13] /* Save in temp storage */
+ mrs lr, spsr /* Get SPSR */
+ str lr, [r13, #4] /* Save in temp storage */
+
+ /* Then switch back to SVC mode */
+
+ bic lr, lr, #MODE_MASK /* Keep F and T bits */
+ orr lr, lr, #(SVC_MODE | PSR_I_BIT)
+ msr cpsr_c, lr /* Switch to SVC mode */
+
+ /* Create a context structure. First set aside a stack frame
+ * and store r0-r12 into the frame.
+ */
+
+ sub sp, sp, #XCPTCONTEXT_SIZE
+ stmia sp, {r0-r12} /* Save the SVC mode regs */
+
+ /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
+
+ add r1, sp, #XCPTCONTEXT_SIZE
+ mov r2, r14
+
+ /* Get the values for r15(pc) and CPSR in r3 and r4 */
+
+ ldr r0, .Lundeftmp /* Points to temp storage */
+ ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
+
+ add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
+ stmia r0, {r1-r4}
+
+ /* Then call the undef insn handler with interrupts disabled.
+ * void up_undefinedinsn(struct xcptcontext *xcp)
+ */
+
+ mov fp, #0 /* Init frame pointer */
+ mov r0, sp /* Get r0=xcp */
+ bl up_undefinedinsn /* Call the handler */
+
+ /* Restore the CPSR, SVC modr registers and return */
+
+ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
+ msr spsr_cxsf, r0
+ ldmia sp, {r0-r15}^ /* Return */
+
+.Lundeftmp:
+ .word g_undeftmp
+ .size up_vectorundefinsn, . - up_vectorundefinsn
+
+ .align 5
+
+/************************************************************************************
+ * Name: up_vectorfiq
+ *
+ * Description:
+ * Shouldn't happen
+ *
+ ************************************************************************************/
+
+ .globl up_vectorfiq
+ .type up_vectorfiq, %function
+up_vectorfiq:
+ subs pc, lr, #4
+ .size up_vectorfiq, . - up_vectorfiq
+
+/************************************************************************************
+ * Name: up_interruptstack/g_userstack
+ ************************************************************************************/
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ .bss
+ .align 4
+ .globl g_userstack
+ .type g_userstack, object
+up_interruptstack:
+ .skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4)
+g_userstack:
+up_stackbase:
+ .skip 4
+ .size g_userstack, 4
+ .size up_interruptstack, (CONFIG_ARCH_INTERRUPTSTACK & ~3)
+#endif
+ .end
diff --git a/nuttx/arch/arm/src/arm/up_vectortab.S b/nuttx/arch/arm/src/arm/up_vectortab.S
new file mode 100644
index 000000000..a7972fa3c
--- /dev/null
+++ b/nuttx/arch/arm/src/arm/up_vectortab.S
@@ -0,0 +1,103 @@
+/****************************************************************************
+ * arch/arm/src/arm/up_vectortab.S
+ *
+ * Copyright (C) 2007, 2009-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Assembly Macros
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: _vector_start
+ *
+ * Description:
+ * Vector initialization block
+ ****************************************************************************/
+
+ .globl _vector_start
+
+/* These will be relocated to VECTOR_BASE. */
+
+_vector_start:
+ ldr pc, .Lresethandler /* 0x00: Reset */
+ ldr pc, .Lundefinedhandler /* 0x04: Undefined instruction */
+ ldr pc, .Lswihandler /* 0x08: Software interrupt */
+ ldr pc, .Lprefetchaborthandler /* 0x0c: Prefetch abort */
+ ldr pc, .Ldataaborthandler /* 0x10: Data abort */
+ ldr pc, .Laddrexcptnhandler /* 0x14: Address exception */
+ ldr pc, .Lirqhandler /* 0x18: IRQ */
+ ldr pc, .Lfiqhandler /* 0x1c: FIQ */
+
+ .globl __start
+ .globl up_vectorundefinsn
+ .globl up_vectorswi
+ .globl up_vectorprefetch
+ .globl up_vectordata
+ .globl up_vectoraddrexcptn
+ .globl up_vectorirq
+ .globl up_vectorfiq
+
+.Lresethandler:
+ .long __start
+.Lundefinedhandler:
+ .long up_vectorundefinsn
+.Lswihandler:
+ .long up_vectorswi
+.Lprefetchaborthandler:
+ .long up_vectorprefetch
+.Ldataaborthandler:
+ .long up_vectordata
+.Laddrexcptnhandler:
+ .long up_vectoraddrexcptn
+.Lirqhandler:
+ .long up_vectorirq
+.Lfiqhandler:
+ .long up_vectorfiq
+
+ .globl _vector_end
+_vector_end:
+ .end
diff --git a/nuttx/arch/arm/src/armv7-m/exc_return.h b/nuttx/arch/arm/src/armv7-m/exc_return.h
new file mode 100644
index 000000000..cffbd3e2e
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/exc_return.h
@@ -0,0 +1,117 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/exc_return.h
+ *
+ * Copyright (C) 2011-2012 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_COMMON_CORTEXM_EXC_RETURN_H
+#define __ARCH_ARM_SRC_COMMON_CORTEXM_EXC_RETURN_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* The processor saves an EXC_RETURN value to the LR on exception entry. The
+ * exception mechanism relies on this value to detect when the processor has
+ * completed an exception handler.
+ *
+ * Bits [31:28] of an EXC_RETURN value are always 1. When the processor loads a
+ * value matching this pattern to the PC it detects that the operation is a not
+ * a normal branch operation and instead, that the exception is complete.
+ * Therefore, it starts the exception return sequence.
+ *
+ * Bits[4:0] of the EXC_RETURN value indicate the required return stack and eventual
+ * processor mode. The remaining bits of the EXC_RETURN value should be set to 1.
+ */
+
+/* EXC_RETURN_BASE: Bits that are always set in an EXC_RETURN value. */
+
+#define EXC_RETURN_BASE 0xffffffe1
+
+/* EXC_RETURN_PROCESS_STACK: The exception saved (and will restore) the hardware
+ * context using the process stack pointer (if not set, the context was saved
+ * using the main stack pointer)
+ */
+
+#define EXC_RETURN_PROCESS_STACK (1 << 2)
+
+/* EXC_RETURN_THREAD_MODE: The exception will return to thread mode (if not set,
+ * return stays in handler mode)
+ */
+
+#define EXC_RETURN_THREAD_MODE (1 << 3)
+
+/* EXC_RETURN_STD_CONTEXT: The state saved on the stack does not include the
+ * volatile FP registers and FPSCR. If this bit is clear, the state does include
+ * these registers.
+ */
+
+#define EXC_RETURN_STD_CONTEXT (1 << 4)
+
+/* EXC_RETURN_HANDLER: Return to handler mode. Exception return gets state from
+ * the main stack. Execution uses MSP after return.
+ */
+
+#define EXC_RETURN_HANDLER 0xfffffff1
+
+/* EXC_RETURN_PRIVTHR: Return to privileged thread mode. Exception return gets
+ * state from the main stack. Execution uses MSP after return.
+ */
+
+#define EXC_RETURN_PRIVTHR 0xfffffff9
+
+/* EXC_RETURN_UNPRIVTHR: Return to unprivileged thread mode. Exception return gets
+ * state from the process stack. Execution uses PSP after return.
+ */
+
+#define EXC_RETURN_UNPRIVTHR 0xfffffffd
+
+/* In the kernel build is not selected, then all threads run in privileged thread
+ * mode.
+ */
+
+#ifdef CONFIG_NUTTX_KERNEL
+# define EXC_RETURN 0xfffffff9
+#endif
+
+/************************Th************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_COMMON_CORTEXM_EXC_RETURN_H */
+
diff --git a/nuttx/arch/arm/src/armv7-m/memcpy.S b/nuttx/arch/arm/src/armv7-m/memcpy.S
new file mode 100644
index 000000000..c6d3ff649
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/memcpy.S
@@ -0,0 +1,351 @@
+@
+@ armv7m-optimised memcpy, apparently in the public domain
+@
+@ Obtained via a posting on the Stellaris forum:
+@ http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/t/44360.aspx
+@
+@ Posted by rocksoft on Jul 24, 2008 10:19 AM
+@
+@ Hi,
+@
+@ I recently finished a "memcpy" replacement and thought it might be useful for others...
+@
+@ I've put some instructions and the code here:
+@
+@ http://www.rock-software.net/downloads/memcpy/
+@
+@ Hope it works for you as well as it did for me.
+@
+@ Liam.
+@ @
+@ ----------------------------------------------------------------------------
+
+.syntax unified
+
+.thumb
+
+.cpu cortex-m3
+
+@ ----------------------------------------------------------------------------
+
+ .global memcpy
+
+
+@ ----------------------------------------------------------------------------
+@ Optimised "general" copy routine
+
+.text
+
+@ We have 16 possible alignment combinations of src and dst, this jump table directs the copy operation
+@ Bits: Src=00, Dst=00 - Long to Long copy
+@ Bits: Src=00, Dst=01 - Long to Byte before half word
+@ Bits: Src=00, Dst=10 - Long to Half word
+@ Bits: Src=00, Dst=11 - Long to Byte before long word
+@ Bits: Src=01, Dst=00 - Byte before half word to long
+@ Bits: Src=01, Dst=01 - Byte before half word to byte before half word - Same alignment
+@ Bits: Src=01, Dst=10 - Byte before half word to half word
+@ Bits: Src=01, Dst=11 - Byte before half word to byte before long word
+@ Bits: Src=10, Dst=00 - Half word to long word
+@ Bits: Src=10, Dst=01 - Half word to byte before half word
+@ Bits: Src=10, Dst=10 - Half word to half word - Same Alignment
+@ Bits: Src=10, Dst=11 - Half word to byte before long word
+@ Bits: Src=11, Dst=00 - Byte before long word to long word
+@ Bits: Src=11, Dst=01 - Byte before long word to byte before half word
+@ Bits: Src=11, Dst=11 - Byte before long word to half word
+@ Bits: Src=11, Dst=11 - Byte before long word to Byte before long word - Same alignment
+
+MEM_DataCopyTable:
+ .byte (MEM_DataCopy0 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy1 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy2 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy3 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy4 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy5 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy6 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy7 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy8 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy9 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy10 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy11 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy12 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy13 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy14 - MEM_DataCopyJump) >> 1
+ .byte (MEM_DataCopy15 - MEM_DataCopyJump) >> 1
+
+ .align 2
+
+@ ----------------------------------------------------------------------------
+
+//#define 10 10
+
+MEM_LongCopyTable:
+ .byte (MEM_LongCopyEnd - MEM_LongCopyJump) >> 1 @ 0 bytes left
+ .byte 0 @ 4 bytes left
+ .byte (1 * 10) >> 1 @ 8 bytes left
+ .byte (2 * 10) >> 1 @ 12 bytes left
+ .byte (3 * 10) >> 1 @ 16 bytes left
+ .byte (4 * 10) >> 1 @ 20 bytes left
+ .byte (5 * 10) >> 1 @ 24 bytes left
+ .byte (6 * 10) >> 1 @ 28 bytes left
+ .byte (7 * 10) >> 1 @ 32 bytes left
+ .byte (8 * 10) >> 1 @ 36 bytes left
+
+ .align 2
+
+@ ----------------------------------------------------------------------------
+@ r0 = destination, r1 = source, r2 = length
+
+.thumb_func
+
+memcpy:
+ push {r14}
+
+ @ This allows the inner workings to "assume" a minimum amount of bytes
+ cmp r2, #4
+ blt MEM_DataCopyBytes
+
+ and r14, r0, #3 @ Get destination alignment bits
+ bfi r14, r1, #2, #2 @ Get source alignment bits
+ ldr r3, =MEM_DataCopyTable @ Jump table base
+ tbb [r3, r14] @ Perform jump on src/dst alignment bits
+MEM_DataCopyJump:
+
+ .align 4
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=01, Dst=01 - Byte before half word to byte before half word - Same alignment
+@ 3 bytes to read for long word aligning
+
+MEM_DataCopy5:
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x01
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=10, Dst=10 - Half word to half word - Same Alignment
+@ 2 bytes to read for long word aligning
+
+MEM_DataCopy10:
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x01
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=11, Dst=11 - Byte before long word to Byte before long word - Same alignment
+@ 1 bytes to read for long word aligning
+
+MEM_DataCopy15:
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x01
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=00, Dst=00 - Long to Long copy
+
+MEM_DataCopy0:
+ @ Save regs
+ push {r4-r12}
+
+ cmp r2, #0x28
+ blt MEM_DataCopy0_2
+
+MEM_DataCopy0_1:
+ ldmia r1!, {r3-r12}
+ stmia r0!, {r3-r12}
+ sub r2, r2, #0x28
+ cmp r2, #0x28
+ bge MEM_DataCopy0_1
+
+MEM_DataCopy0_2:
+ @ Copy remaining long words
+ ldr r14, =MEM_LongCopyTable
+ lsr r11, r2, #0x02
+ tbb [r14, r11]
+
+MEM_LongCopyJump:
+ ldr.w r3, [r1], #0x04 @ 4 bytes remain
+ str.w r3, [r0], #0x04
+ b MEM_LongCopyEnd
+ ldmia.w r1!, {r3-r4} @ 8 bytes remain
+ stmia.w r0!, {r3-r4}
+ b MEM_LongCopyEnd
+ ldmia.w r1!, {r3-r5} @ 12 bytes remain
+ stmia.w r0!, {r3-r5}
+ b MEM_LongCopyEnd
+ ldmia.w r1!, {r3-r6} @ 16 bytes remain
+ stmia.w r0!, {r3-r6}
+ b MEM_LongCopyEnd
+ ldmia.w r1!, {r3-r7} @ 20 bytes remain
+ stmia.w r0!, {r3-r7}
+ b MEM_LongCopyEnd
+ ldmia.w r1!, {r3-r8} @ 24 bytes remain
+ stmia.w r0!, {r3-r8}
+ b MEM_LongCopyEnd
+ ldmia.w r1!, {r3-r9} @ 28 bytes remain
+ stmia.w r0!, {r3-r9}
+ b MEM_LongCopyEnd
+ ldmia.w r1!, {r3-r10} @ 32 bytes remain
+ stmia.w r0!, {r3-r10}
+ b MEM_LongCopyEnd
+ ldmia.w r1!, {r3-r11} @ 36 bytes remain
+ stmia.w r0!, {r3-r11}
+
+MEM_LongCopyEnd:
+ pop {r4-r12}
+ and r2, r2, #0x03 @ All the longs have been copied
+
+@ ----------------------------------------------------------------------------
+
+MEM_DataCopyBytes:
+ @ Deal with up to 3 remaining bytes
+ cmp r2, #0x00
+ it eq
+ popeq {pc}
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ subs r2, r2, #0x01
+ it eq
+ popeq {pc}
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ subs r2, r2, #0x01
+ it eq
+ popeq {pc}
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ pop {pc}
+
+ .align 4
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=01, Dst=11 - Byte before half word to byte before long word
+@ 3 bytes to read for long word aligning the source
+
+MEM_DataCopy7:
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x01
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=10, Dst=00 - Half word to long word
+@ 2 bytes to read for long word aligning the source
+
+MEM_DataCopy8:
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x01
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=11, Dst=01 - Byte before long word to byte before half word
+@ 1 byte to read for long word aligning the source
+
+MEM_DataCopy13:
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x01
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=00, Dst=10 - Long to Half word
+
+MEM_DataCopy2:
+ cmp r2, #0x28
+ blt MEM_DataCopy2_1
+
+ @ Save regs
+ push {r4-r12}
+MEM_DataCopy2_2:
+ ldmia r1!, {r3-r12}
+
+ strh r3, [r0], #0x02
+
+ lsr r3, r3, #0x10
+ bfi r3, r4, #0x10, #0x10
+ lsr r4, r4, #0x10
+ bfi r4, r5, #0x10, #0x10
+ lsr r5, r5, #0x10
+ bfi r5, r6, #0x10, #0x10
+ lsr r6, r6, #0x10
+ bfi r6, r7, #0x10, #0x10
+ lsr r7, r7, #0x10
+ bfi r7, r8, #0x10, #0x10
+ lsr r8, r8, #0x10
+ bfi r8, r9, #0x10, #0x10
+ lsr r9, r9, #0x10
+ bfi r9, r10, #0x10, #0x10
+ lsr r10, r10, #0x10
+ bfi r10, r11, #0x10, #0x10
+ lsr r11, r11, #0x10
+ bfi r11, r12, #0x10, #0x10
+ stmia r0!, {r3-r11}
+ lsr r12, r12, #0x10
+ strh r12, [r0], #0x02
+
+ sub r2, r2, #0x28
+ cmp r2, #0x28
+ bge MEM_DataCopy2_2
+ pop {r4-r12}
+
+MEM_DataCopy2_1: @ Read longs and write 2 x half words
+ cmp r2, #4
+ blt MEM_DataCopyBytes
+ ldr r3, [r1], #0x04
+ strh r3, [r0], #0x02
+ lsr r3, r3, #0x10
+ strh r3, [r0], #0x02
+ sub r2, r2, #0x04
+ b MEM_DataCopy2
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=01, Dst=00 - Byte before half word to long
+@ Bits: Src=01, Dst=10 - Byte before half word to half word
+@ 3 bytes to read for long word aligning the source
+
+MEM_DataCopy4:
+MEM_DataCopy6:
+ @ Read B and write B
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x01
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=10, Dst=01 - Half word to byte before half word
+@ Bits: Src=10, Dst=11 - Half word to byte before long word
+@ 2 bytes to read for long word aligning the source
+
+MEM_DataCopy9:
+MEM_DataCopy11:
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x01
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=11, Dst=00 - Byte before long word to long word
+@ Bits: Src=11, Dst=11 - Byte before long word to half word
+@ 1 byte to read for long word aligning the source
+
+MEM_DataCopy12:
+MEM_DataCopy14:
+ @ Read B and write B
+ ldrb r3, [r1], #0x01
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x01
+
+@ ----------------------------------------------------------------------------
+@ Bits: Src=00, Dst=01 - Long to Byte before half word
+@ Bits: Src=00, Dst=11 - Long to Byte before long word
+
+MEM_DataCopy1: @ Read longs, write B->H->B
+MEM_DataCopy3:
+ cmp r2, #4
+ blt MEM_DataCopyBytes
+ ldr r3, [r1], #0x04
+ strb r3, [r0], #0x01
+ lsr r3, r3, #0x08
+ strh r3, [r0], #0x02
+ lsr r3, r3, #0x10
+ strb r3, [r0], #0x01
+ sub r2, r2, #0x04
+ b MEM_DataCopy3
+
+@ ----------------------------------------------------------------------------
+
diff --git a/nuttx/arch/arm/src/armv7-m/mpu.h b/nuttx/arch/arm/src/armv7-m/mpu.h
new file mode 100644
index 000000000..8d4cd1829
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/mpu.h
@@ -0,0 +1,509 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/mpu.h
+ *
+ * Copyright (C) 2011 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_COMMON_CORTEXM_MPU_H
+#define __ARCH_ARM_SRC_COMMON_CORTEXM_MPU_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifndef __ASSEMBLY__
+# include <sys/types.h>
+# include <stdint.h>
+# include <stdbool.h>
+# include <debug.h>
+
+# include "up_arch.h"
+#endif
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* MPU Register Addresses */
+
+#define MPU_TYPE 0xe000ed90 /* MPU Type Register */
+#define MPU_CTRL 0xe000ed94 /* MPU Control Register */
+#define MPU_RNR 0xe000ed98 /* MPU Region Number Register */
+#define MPU_RBAR 0xe000ed9c /* MPU Region Base Address Register */
+#define MPU_RASR 0xe000eda0 /* MPU Region Attribute and Size Register */
+
+/* MPU Type Register Bit Definitions */
+
+#define MPU_TYPE_SEPARATE (1 << 0) /* Bit 0: 0:unified or 1:separate memory maps */
+#define MPU_TYPE_DREGION_SHIFT (8) /* Bits 8-15: Number MPU data regsion */
+#define MPU_TYPE_DREGION_MASK (0xff << MPU_TYPE_DREGION_SHIFT)
+#define MPU_TYPE_IREGION_SHIFT (16) /* Bits 16-23: Number MPU instruction regions */
+#define MPU_TYPE_IREGION_MASK (0xff << MPU_TYPE_IREGION_SHIFT)
+
+/* MPU Control Register Bit Definitions */
+
+#define MPU_CTRL_ENABLE (1 << 0) /* Bit 0: Enable the MPU */
+#define MPU_CTRL_HFNMIENA (1 << 1) /* Bit 1: Enable MPU during hard fault, NMI, and FAULTMAS */
+#define MPU_CTRL_PRIVDEFENA (1 << 2) /* Bit 2: Enable privileged access to default memory map */
+
+/* MPU Region Number Register Bit Definitions */
+
+#define MPU_RNR_MASK (0xff)
+
+/* MPU Region Base Address Register Bit Definitions */
+
+#define MPU_RBAR_REGION_SHIFT (0) /* Bits 0-3: MPU region */
+#define MPU_RBAR_REGION_MASK (15 << MPU_RBAR_REGION_SHIFT)
+#define MPU_RBAR_VALID (1 << 4) /* Bit 4: MPU Region Number valid */
+#define MPU_RBAR_ADDR_MASK 0xffffffe0 /* Bits N-31: Region base addrese */
+
+/* MPU Region Attributes and Size Register Bit Definitions */
+
+#define MPU_RASR_ENABLE (1 << 0) /* Bit 0: Region enable */
+#define MPU_RASR_SIZE_SHIFT (1) /* Bits 1-5: Size of the MPU protection region */
+#define MPU_RASR_SIZE_MASK (31 << MPU_RASR_SIZE_SHIFT)
+# define MPU_RASR_SIZE_LOG2(n) ((n-1) << MPU_RASR_SIZE_SHIFT)
+#define MPU_RASR_SRD_SHIFT (8) /* Bits 8-15: Subregion disable */
+#define MPU_RASR_SRD_MASK (0xff << MPU_RASR_SRD_SHIFT)
+# define MPU_RASR_SRD_0 (0x01 << MPU_RASR_SRD_SHIFT)
+# define MPU_RASR_SRD_1 (0x02 << MPU_RASR_SRD_SHIFT)
+# define MPU_RASR_SRD_2 (0x04 << MPU_RASR_SRD_SHIFT)
+# define MPU_RASR_SRD_3 (0x08 << MPU_RASR_SRD_SHIFT)
+# define MPU_RASR_SRD_4 (0x10 << MPU_RASR_SRD_SHIFT)
+# define MPU_RASR_SRD_5 (0x20 << MPU_RASR_SRD_SHIFT)
+# define MPU_RASR_SRD_6 (0x40 << MPU_RASR_SRD_SHIFT)
+# define MPU_RASR_SRD_7 (0x80 << MPU_RASR_SRD_SHIFT)
+#define MPU_RASR_ATTR_SHIFT (21) /* Bits 19-21: TEX Address Permisson */
+#define MPU_RASR_ATTR__MASK (7 << MPU_RASR_ATTR_SHIFT)
+#define MPU_RASR_S (1 << 18) /* Bit 18: Shareable */
+#define MPU_RASR_C (1 << 17) /* Bit 17: Cacheable */
+#define MPU_RASR_B (1 << 16) /* Bit 16: Bufferable */
+#define MPU_RASR_AP_SHIFT (24) /* Bits 24-26: Access permission */
+#define MPU_RASR_AP_MASK (7 << MPU_RASR_AP_SHIFT)
+# define MPU_RASR_AP_NONO (0 << MPU_RASR_AP_SHIFT) /* P:None U:None */
+# define MPU_RASR_AP_RWNO (1 << MPU_RASR_AP_SHIFT) /* P:RW U:None */
+# define MPU_RASR_AP_RWRO (2 << MPU_RASR_AP_SHIFT) /* P:RW U:RO */
+# define MPU_RASR_AP_RWRW (3 << MPU_RASR_AP_SHIFT) /* P:RW U:RW */
+# define MPU_RASR_AP_RONO (5 << MPU_RASR_AP_SHIFT) /* P:RO U:None */
+# define MPU_RASR_AP_RORO (6 << MPU_RASR_AP_SHIFT) /* P:RO U:RO */
+#define MPU_RASR_XN (1 << 28) /* Bit 28: Instruction access disable */
+
+/************************************************************************************
+ * Global Function Prototypes
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: mpu_allocregion
+ *
+ * Description:
+ * Allocate the next region
+ *
+ ****************************************************************************/
+
+EXTERN unsigned int mpu_allocregion(void);
+
+/****************************************************************************
+ * Name: mpu_log2regionsize
+ *
+ * Description:
+ * Determine the smallest value of l2size (log base 2 size) such that the
+ * following is true:
+ *
+ * size <= (1 << l2size)
+ *
+ ****************************************************************************/
+
+EXTERN uint8_t mpu_log2regionsize(size_t size);
+
+/****************************************************************************
+ * Name: mpu_subregion
+ *
+ * Description:
+ * Given the size of the (1) memory to be mapped and (2) the log2 size
+ * of the mapping to use, determine the minimal sub-region set to span
+ * that memory region.
+ *
+ * Assumption:
+ * l2size has the same properties as the return value from
+ * mpu_log2regionsize()
+ *
+ ****************************************************************************/
+
+EXTERN uint32_t mpu_subregion(size_t size, uint8_t l2size);
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/****************************************************************************
+ * Name: mpu_showtype
+ *
+ * Description:
+ * Show the characteristics of the MPU
+ *
+ ****************************************************************************/
+
+static inline void mpu_showtype(void)
+{
+#ifdef CONFIG_DEBUG
+ uint32_t regval = getreg32(MPU_TYPE);
+ dbg("%s MPU Regions: data=%d instr=%d\n",
+ (regval & MPU_TYPE_SEPARATE) != 0 ? "Separate" : "Unified",
+ (regval & MPU_TYPE_DREGION_MASK) >> MPU_TYPE_DREGION_SHIFT,
+ (regval & MPU_TYPE_IREGION_MASK) >> MPU_TYPE_IREGION_SHIFT);
+#endif
+}
+
+/****************************************************************************
+ * Name: mpu_control
+ *
+ * Description:
+ * Configure and enable (or disable) the MPU
+ *
+ ****************************************************************************/
+
+static inline void mpu_control(bool enable, bool hfnmiena, bool privdefena)
+{
+ uint32_t regval = 0;
+
+ if (enable)
+ {
+ regval |= MPU_CTRL_ENABLE; /* Enable the MPU */
+
+ if (hfnmiena)
+ {
+ regval |= MPU_CTRL_HFNMIENA; /* Enable MPU during hard fault, NMI, and FAULTMAS */
+ }
+
+ if (privdefena)
+ {
+ regval |= MPU_CTRL_PRIVDEFENA; /* Enable privileged access to default memory map */
+ }
+ }
+
+ putreg32(regval, MPU_CTRL);
+}
+
+/****************************************************************************
+ * Name: mpu_userflash
+ *
+ * Description:
+ * Configure a region for user program flash
+ *
+ ****************************************************************************/
+
+static inline void mpu_userflash(uintptr_t base, size_t size)
+{
+ unsigned int region = mpu_allocregion();
+ uint32_t regval;
+ uint8_t l2size;
+ uint8_t subregions;
+
+ /* Select the region */
+
+ putreg32(region, MPU_RNR);
+
+ /* Select the region base address */
+
+ putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR);
+
+ /* Select the region size and the sub-region map */
+
+ l2size = mpu_log2regionsize(size);
+ subregions = mpu_subregion(size, l2size);
+
+ /* The configure the region */
+
+ regval = MPU_RASR_ENABLE | /* Enable region */
+ MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */
+ ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */
+ MPU_RASR_C | /* Cacheable */
+ MPU_RASR_AP_RORO; /* P:RO U:RO */
+ putreg32(regval, MPU_RASR);
+}
+
+/****************************************************************************
+ * Name: mpu_privflash
+ *
+ * Description:
+ * Configure a region for privileged program flash
+ *
+ ****************************************************************************/
+
+static inline void mpu_privflash(uintptr_t base, size_t size)
+{
+ unsigned int region = mpu_allocregion();
+ uint32_t regval;
+ uint8_t l2size;
+ uint8_t subregions;
+
+ /* Select the region */
+
+ putreg32(mpu_allocregion(), MPU_RNR);
+
+ /* Select the region base address */
+
+ putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR);
+
+ /* Select the region size and the sub-region map */
+
+ l2size = mpu_log2regionsize(size);
+ subregions = mpu_subregion(size, l2size);
+
+ /* The configure the region */
+
+ regval = MPU_RASR_ENABLE | /* Enable region */
+ MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */
+ ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */
+ MPU_RASR_C | /* Cacheable */
+ MPU_RASR_AP_RONO; /* P:RO U:None */
+ putreg32(regval, MPU_RASR);
+}
+
+/****************************************************************************
+ * Name: mpu_userintsram
+ *
+ * Description:
+ * Configure a region as user internal SRAM
+ *
+ ****************************************************************************/
+
+static inline void mpu_userintsram(uintptr_t base, size_t size)
+{
+ unsigned int region = mpu_allocregion();
+ uint32_t regval;
+ uint8_t l2size;
+ uint8_t subregions;
+
+ /* Select the region */
+
+ putreg32(region, MPU_RNR);
+
+ /* Select the region base address */
+
+ putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR);
+
+ /* Select the region size and the sub-region map */
+
+ l2size = mpu_log2regionsize(size);
+ subregions = mpu_subregion(size, l2size);
+
+ /* The configure the region */
+
+ regval = MPU_RASR_ENABLE | /* Enable region */
+ MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */
+ ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */
+ MPU_RASR_S | /* Shareable */
+ MPU_RASR_C | /* Cacheable */
+ MPU_RASR_AP_RWRW; /* P:RW U:RW */
+ putreg32(regval, MPU_RASR);
+}
+
+/****************************************************************************
+ * Name: mpu_privintsram
+ *
+ * Description:
+ * Configure a region as privileged internal SRAM
+ *
+ ****************************************************************************/
+
+static inline void mpu_privintsram(uintptr_t base, size_t size)
+{
+ unsigned int region = mpu_allocregion();
+ uint32_t regval;
+ uint8_t l2size;
+ uint8_t subregions;
+
+ /* Select the region */
+
+ putreg32(region, MPU_RNR);
+
+ /* Select the region base address */
+
+ putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR);
+
+ /* Select the region size and the sub-region map */
+
+ l2size = mpu_log2regionsize(size);
+ subregions = mpu_subregion(size, l2size);
+
+ /* The configure the region */
+
+ regval = MPU_RASR_ENABLE | /* Enable region */
+ MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */
+ ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */
+ MPU_RASR_S | /* Shareable */
+ MPU_RASR_C | /* Cacheable */
+ MPU_RASR_AP_RWNO; /* P:RW U:None */
+ putreg32(regval, MPU_RASR);
+}
+
+/****************************************************************************
+ * Name: mpu_userextsram
+ *
+ * Description:
+ * Configure a region as user external SRAM
+ *
+ ****************************************************************************/
+
+static inline void mpu_userextsram(uintptr_t base, size_t size)
+{
+ unsigned int region = mpu_allocregion();
+ uint32_t regval;
+ uint8_t l2size;
+ uint8_t subregions;
+
+ /* Select the region */
+
+ putreg32(region, MPU_RNR);
+
+ /* Select the region base address */
+
+ putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR);
+
+ /* Select the region size and the sub-region map */
+
+ l2size = mpu_log2regionsize(size);
+ subregions = mpu_subregion(size, l2size);
+
+ /* The configure the region */
+
+ regval = MPU_RASR_ENABLE | /* Enable region */
+ MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */
+ ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */
+ MPU_RASR_S | /* Shareable */
+ MPU_RASR_C | /* Cacheable */
+ MPU_RASR_B | /* Bufferable */
+ MPU_RASR_AP_RWRW; /* P:RW U:RW */
+ putreg32(regval, MPU_RASR);
+}
+
+/****************************************************************************
+ * Name: mpu_privextsram
+ *
+ * Description:
+ * Configure a region as privileged external SRAM
+ *
+ ****************************************************************************/
+
+static inline void mpu_privextsram(uintptr_t base, size_t size)
+{
+ unsigned int region = mpu_allocregion();
+ uint32_t regval;
+ uint8_t l2size;
+ uint8_t subregions;
+
+ /* Select the region */
+
+ putreg32(region, MPU_RNR);
+
+ /* Select the region base address */
+
+ putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR);
+
+ /* Select the region size and the sub-region map */
+
+ l2size = mpu_log2regionsize(size);
+ subregions = mpu_subregion(size, l2size);
+
+ /* The configure the region */
+
+ regval = MPU_RASR_ENABLE | /* Enable region */
+ MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */
+ ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */
+ MPU_RASR_S | /* Shareable */
+ MPU_RASR_C | /* Cacheable */
+ MPU_RASR_B | /* Bufferable */
+ MPU_RASR_AP_RWNO; /* P:RW U:None */
+ putreg32(regval, MPU_RASR);
+}
+
+/****************************************************************************
+ * Name: mpu_peripheral
+ *
+ * Description:
+ * Configure a region as privileged periperal address space
+ *
+ ****************************************************************************/
+
+static inline void mpu_peripheral(uintptr_t base, size_t size)
+{
+ unsigned int region = mpu_allocregion();
+ uint32_t regval;
+ uint8_t l2size;
+ uint8_t subregions;
+
+ /* Select the region */
+
+ putreg32(region, MPU_RNR);
+
+ /* Select the region base address */
+
+ putreg32((base & MPU_RBAR_ADDR_MASK) | region, MPU_RBAR);
+
+ /* Select the region size and the sub-region map */
+
+ l2size = mpu_log2regionsize(size);
+ subregions = mpu_subregion(size, l2size);
+
+ /* The configure the region */
+
+ regval = MPU_RASR_ENABLE | /* Enable region */
+ MPU_RASR_SIZE_LOG2((uint32_t)l2size) | /* Region size */
+ ((uint32_t)subregions << MPU_RASR_SRD_SHIFT) | /* Sub-regions */
+ MPU_RASR_S | /* Shareable */
+ MPU_RASR_B | /* Bufferable */
+ MPU_RASR_AP_RWNO | /* P:RW U:None */
+ MPU_RASR_XN | /* Instruction access disable */
+
+ putreg32(regval, MPU_RASR);
+}
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_COMMON_CORTEXM_MPU_H */
+
diff --git a/nuttx/arch/arm/src/armv7-m/nvic.h b/nuttx/arch/arm/src/armv7-m/nvic.h
new file mode 100644
index 000000000..1d30c5f7c
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/nvic.h
@@ -0,0 +1,531 @@
+/********************************************************************************************
+ * arch/arm/src/armv7-m/nvic.h
+ *
+ * Copyright (C) 2009, 2011 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_COMMON_ARMV7_M_NVIC_H
+#define __ARCH_ARM_SRC_COMMON_ARMV7_M_NVIC_H
+
+/********************************************************************************************
+ * Included Files
+ ********************************************************************************************/
+
+#include <nuttx/config.h>
+
+/********************************************************************************************
+ * Pre-processor Definitions
+ ********************************************************************************************/
+
+/* NVIC base address ************************************************************************/
+
+#define ARMV7M_NVIC_BASE 0xe000e000
+
+/* NVIC register offsets ********************************************************************/
+
+#define NVIC_ICTR_OFFSET 0x0004 /* Interrupt controller type register */
+#define NVIC_SYSTICK_CTRL_OFFSET 0x0010 /* SysTick control and status register */
+#define NVIC_SYSTICK_RELOAD_OFFSET 0x0014 /* SysTick reload value register */
+#define NVIC_SYSTICK_CURRENT_OFFSET 0x0018 /* SysTick current value register */
+#define NVIC_SYSTICK_CALIB_OFFSET 0x001c /* SysTick calibration value register */
+
+#define NVIC_IRQ_ENABLE_OFFSET(n) (0x0100 + 4*((n) >> 5))
+#define NVIC_IRQ0_31_ENABLE_OFFSET 0x0100 /* IRQ 0-31 set enable register */
+#define NVIC_IRQ32_63_ENABLE_OFFSET 0x0104 /* IRQ 32-63 set enable register */
+#define NVIC_IRQ64_95_ENABLE_OFFSET 0x0108 /* IRQ 64-95 set enable register */
+#define NVIC_IRQ96_127_ENABLE_OFFSET 0x010c /* IRQ 96-127 set enable register */
+#define NVIC_IRQ128_159_ENABLE_OFFSET 0x0110 /* IRQ 128-159 set enable register */
+#define NVIC_IRQ160_191_ENABLE_OFFSET 0x0114 /* IRQ 160-191 set enable register */
+#define NVIC_IRQ192_223_ENABLE_OFFSET 0x0118 /* IRQ 192-223 set enable register */
+#define NVIC_IRQ224_239_ENABLE_OFFSET 0x011c /* IRQ 224-239 set enable register */
+
+#define NVIC_IRQ_CLEAR_OFFSET(n) (0x0180 + 4*((n) >> 5))
+#define NVIC_IRQ0_31_CLEAR_OFFSET 0x0180 /* IRQ 0-31 clear enable register */
+#define NVIC_IRQ32_63_CLEAR_OFFSET 0x0184 /* IRQ 32-63 clear enable register */
+#define NVIC_IRQ64_95_CLEAR_OFFSET 0x0188 /* IRQ 64-95 clear enable register */
+#define NVIC_IRQ96_127_CLEAR_OFFSET 0x018c /* IRQ 96-127 clear enable register */
+#define NVIC_IRQ128_159_CLEAR_OFFSET 0x0190 /* IRQ 128-159 clear enable register */
+#define NVIC_IRQ160_191_CLEAR_OFFSET 0x0194 /* IRQ 160-191 clear enable register */
+#define NVIC_IRQ192_223_CLEAR_OFFSET 0x0198 /* IRQ 192-223 clear enable register */
+#define NVIC_IRQ224_239_CLEAR_OFFSET 0x019c /* IRQ 224-2391 clear enable register */
+
+#define NVIC_IRQ_PEND_OFFSET(n) (0x0200 + 4*((n) >> 5))
+#define NVIC_IRQ0_31_PEND_OFFSET 0x0200 /* IRQ 0-31 set pending register */
+#define NVIC_IRQ32_63_PEND_OFFSET 0x0204 /* IRQ 32-63 set pending register */
+#define NVIC_IRQ64_95_PEND_OFFSET 0x0208 /* IRQ 64-95 set pending register */
+#define NVIC_IRQ96_127_PEND_OFFSET 0x020c /* IRQ 96-127 set pending register */
+#define NVIC_IRQ128_159_PEND_OFFSET 0x0210 /* IRQ 128-159 set pending register */
+#define NVIC_IRQ160_191_PEND_OFFSET 0x0214 /* IRQ 160-191 set pending register */
+#define NVIC_IRQ192_223_PEND_OFFSET 0x0218 /* IRQ 192-2231 set pending register */
+#define NVIC_IRQ224_239_PEND_OFFSET 0x021c /* IRQ 224-2391 set pending register */
+
+#define NVIC_IRQ_CLRPEND_OFFSET(n) (0x0280 + 4*((n) >> 5))
+#define NVIC_IRQ0_31_CLRPEND_OFFSET 0x0280 /* IRQ 0-31 clear pending register */
+#define NVIC_IRQ32_63_CLRPEND_OFFSET 0x0284 /* IRQ 32-63 clear pending register */
+#define NVIC_IRQ64_95_CLRPEND_OFFSET 0x0288 /* IRQ 64-95 clear pending register */
+#define NVIC_IRQ96_127_CLRPEND_OFFSET 0x028c /* IRQ 96-127 clear pending register */
+#define NVIC_IRQ128_159_CLRPEND_OFFSET 0x0290 /* IRQ 128-159 clear pending register */
+#define NVIC_IRQ160_191_CLRPEND_OFFSET 0x0294 /* IRQ 160-191 clear pending register */
+#define NVIC_IRQ192_223_CLRPEND_OFFSET 0x0298 /* IRQ 192-223 clear pending register */
+#define NVIC_IRQ224_239_CLRPEND_OFFSET 0x029c /* IRQ 224-239 clear pending register */
+
+#define NVIC_IRQ_ACTIVE_OFFSET(n) (0x0300 + 4*((n) >> 5))
+#define NVIC_IRQ0_31_ACTIVE_OFFSET 0x0300 /* IRQ 0-31 active bit register */
+#define NVIC_IRQ32_63_ACTIVE_OFFSET 0x0304 /* IRQ 32-63 active bit register */
+#define NVIC_IRQ64_95_ACTIVE_OFFSET 0x0308 /* IRQ 64-95 active bit register */
+#define NVIC_IRQ96_127_ACTIVE_OFFSET 0x030c /* IRQ 96-127 active bit register */
+#define NVIC_IRQ128_159_ACTIVE_OFFSET 0x0310 /* IRQ 128-159 active bit register */
+#define NVIC_IRQ160_191_ACTIVE_OFFSET 0x0314 /* IRQ 160-191 active bit register */
+#define NVIC_IRQ192_223_ACTIVE_OFFSET 0x0318 /* IRQ 192-223 active bit register */
+#define NVIC_IRQ224_239_ACTIVE_OFFSET 0x031c /* IRQ 224-239 active bit register */
+
+#define NVIC_IRQ_PRIORITY_OFFSET(n) (0x0400 + 4*((n) >> 2))
+#define NVIC_IRQ0_3_PRIORITY_OFFSET 0x0400 /* IRQ 0-3 priority register */
+#define NVIC_IRQ4_7_PRIORITY_OFFSET 0x0404 /* IRQ 4-7 priority register */
+#define NVIC_IRQ8_11_PRIORITY_OFFSET 0x0408 /* IRQ 8-11 priority register */
+#define NVIC_IRQ12_15_PRIORITY_OFFSET 0x040c /* IRQ 12-15 priority register */
+#define NVIC_IRQ16_19_PRIORITY_OFFSET 0x0410 /* IRQ 16-19 priority register */
+#define NVIC_IRQ20_23_PRIORITY_OFFSET 0x0414 /* IRQ 20-23 priority register */
+#define NVIC_IRQ24_27_PRIORITY_OFFSET 0x0418 /* IRQ 24-29 priority register */
+#define NVIC_IRQ28_31_PRIORITY_OFFSET 0x041c /* IRQ 28-31 priority register */
+#define NVIC_IRQ32_35_PRIORITY_OFFSET 0x0420 /* IRQ 32-35 priority register */
+#define NVIC_IRQ36_39_PRIORITY_OFFSET 0x0424 /* IRQ 36-39 priority register */
+#define NVIC_IRQ40_43_PRIORITY_OFFSET 0x0428 /* IRQ 40-43 priority register */
+#define NVIC_IRQ44_47_PRIORITY_OFFSET 0x042c /* IRQ 44-47 priority register */
+#define NVIC_IRQ48_51_PRIORITY_OFFSET 0x0430 /* IRQ 48-51 priority register */
+#define NVIC_IRQ52_55_PRIORITY_OFFSET 0x0434 /* IRQ 52-55 priority register */
+#define NVIC_IRQ56_59_PRIORITY_OFFSET 0x0438 /* IRQ 56-59 priority register */
+#define NVIC_IRQ60_63_PRIORITY_OFFSET 0x043c /* IRQ 60-63 priority register */
+#define NVIC_IRQ64_67_PRIORITY_OFFSET 0x0440 /* IRQ 64-67 priority register */
+#define NVIC_IRQ68_71_PRIORITY_OFFSET 0x0444 /* IRQ 68-71 priority register */
+#define NVIC_IRQ72_75_PRIORITY_OFFSET 0x0448 /* IRQ 72-75 priority register */
+#define NVIC_IRQ76_79_PRIORITY_OFFSET 0x044c /* IRQ 76-79 priority register */
+#define NVIC_IRQ80_83_PRIORITY_OFFSET 0x0450 /* IRQ 80-83 priority register */
+#define NVIC_IRQ84_87_PRIORITY_OFFSET 0x0454 /* IRQ 84-87 priority register */
+#define NVIC_IRQ88_91_PRIORITY_OFFSET 0x0458 /* IRQ 88-91 priority register */
+#define NVIC_IRQ92_95_PRIORITY_OFFSET 0x045c /* IRQ 92-95 priority register */
+#define NVIC_IRQ96_99_PRIORITY_OFFSET 0x0460 /* IRQ 96-99 priority register */
+#define NVIC_IRQ100_103_PRIORITY_OFFSET 0x0464 /* IRQ 100-103 priority register */
+#define NVIC_IRQ104_107_PRIORITY_OFFSET 0x0468 /* IRQ 104-107 priority register */
+#define NVIC_IRQ108_111_PRIORITY_OFFSET 0x046c /* IRQ 108-111 priority register */
+#define NVIC_IRQ112_115_PRIORITY_OFFSET 0x0470 /* IRQ 112-115 priority register */
+#define NVIC_IRQ116_119_PRIORITY_OFFSET 0x0474 /* IRQ 116-119 priority register */
+#define NVIC_IRQ120_123_PRIORITY_OFFSET 0x0478 /* IRQ 120-123 priority register */
+#define NVIC_IRQ124_127_PRIORITY_OFFSET 0x047c /* IRQ 124-127 priority register */
+#define NVIC_IRQ128_131_PRIORITY_OFFSET 0x0480 /* IRQ 128-131 priority register */
+#define NVIC_IRQ132_135_PRIORITY_OFFSET 0x0484 /* IRQ 132-135 priority register */
+#define NVIC_IRQ136_139_PRIORITY_OFFSET 0x0488 /* IRQ 136-139 priority register */
+#define NVIC_IRQ140_143_PRIORITY_OFFSET 0x048c /* IRQ 140-143 priority register */
+#define NVIC_IRQ144_147_PRIORITY_OFFSET 0x0490 /* IRQ 144-147 priority register */
+#define NVIC_IRQ148_151_PRIORITY_OFFSET 0x0494 /* IRQ 148-151 priority register */
+#define NVIC_IRQ152_155_PRIORITY_OFFSET 0x0498 /* IRQ 152-155 priority register */
+#define NVIC_IRQ156_159_PRIORITY_OFFSET 0x049c /* IRQ 156-159 priority register */
+#define NVIC_IRQ160_163_PRIORITY_OFFSET 0x04a0 /* IRQ 160-163 priority register */
+#define NVIC_IRQ164_167_PRIORITY_OFFSET 0x04a4 /* IRQ 164-167 priority register */
+#define NVIC_IRQ168_171_PRIORITY_OFFSET 0x04a8 /* IRQ 168-171 priority register */
+#define NVIC_IRQ172_175_PRIORITY_OFFSET 0x04ac /* IRQ 172-175 priority register */
+#define NVIC_IRQ176_179_PRIORITY_OFFSET 0x04b0 /* IRQ 176-179 priority register */
+#define NVIC_IRQ180_183_PRIORITY_OFFSET 0x04b4 /* IRQ 180-183 priority register */
+#define NVIC_IRQ184_187_PRIORITY_OFFSET 0x04b8 /* IRQ 184-187 priority register */
+#define NVIC_IRQ188_191_PRIORITY_OFFSET 0x04bc /* IRQ 188-191 priority register */
+#define NVIC_IRQ192_195_PRIORITY_OFFSET 0x04c0 /* IRQ 192-195 priority register */
+#define NVIC_IRQ196_199_PRIORITY_OFFSET 0x04c4 /* IRQ 196-199 priority register */
+#define NVIC_IRQ200_203_PRIORITY_OFFSET 0x04c8 /* IRQ 200-203 priority register */
+#define NVIC_IRQ204_207_PRIORITY_OFFSET 0x04cc /* IRQ 204-207 priority register */
+#define NVIC_IRQ208_211_PRIORITY_OFFSET 0x04d0 /* IRQ 208-211 priority register */
+#define NVIC_IRQ212_215_PRIORITY_OFFSET 0x04d4 /* IRQ 212-215 priority register */
+#define NVIC_IRQ216_219_PRIORITY_OFFSET 0x04d8 /* IRQ 216-219 priority register */
+#define NVIC_IRQ220_223_PRIORITY_OFFSET 0x04dc /* IRQ 220-223 priority register */
+#define NVIC_IRQ224_227_PRIORITY_OFFSET 0x04e0 /* IRQ 224-227 priority register */
+#define NVIC_IRQ228_231_PRIORITY_OFFSET 0x04e4 /* IRQ 228-231 priority register */
+#define NVIC_IRQ232_235_PRIORITY_OFFSET 0x04e8 /* IRQ 232-235 priority register */
+#define NVIC_IRQ236_239_PRIORITY_OFFSET 0x04ec /* IRQ 236-239 priority register */
+
+/* System Control Block (SCB) */
+
+#define NVIC_CPUID_BASE_OFFSET 0x0d00 /* CPUID base register */
+#define NVIC_INTCTRL_OFFSET 0x0d04 /* Interrupt control state register */
+#define NVIC_VECTAB_OFFSET 0x0d08 /* Vector table offset register */
+#define NVIC_AIRC_OFFSET 0x0d0c /* Application interrupt/reset contol registr */
+#define NVIC_SYSCON_OFFSET 0x0d10 /* System control register */
+#define NVIC_CFGCON_OFFSET 0x0d14 /* Configuration control register */
+#define NVIC_SYSH_PRIORITY_OFFSET(n) (0x0d14 + 4*((n) >> 2))
+#define NVIC_SYSH4_7_PRIORITY_OFFSET 0x0d18 /* System handlers 4-7 priority register */
+#define NVIC_SYSH8_11_PRIORITY_OFFSET 0x0d1c /* System handler 8-11 priority register */
+#define NVIC_SYSH12_15_PRIORITY_OFFSET 0x0d20 /* System handler 12-15 priority register */
+#define NVIC_SYSHCON_OFFSET 0x0d24 /* System handler control and state register */
+#define NVIC_CFAULTS_OFFSET 0x0d28 /* Configurable fault status register */
+#define NVIC_HFAULTS_OFFSET 0x0d2c /* Hard fault status register */
+#define NVIC_DFAULTS_OFFSET 0x0d30 /* Debug fault status register */
+#define NVIC_MEMMANAGE_ADDR_OFFSET 0x0d34 /* Mem manage address register */
+#define NVIC_BFAULT_ADDR_OFFSET 0x0d38 /* Bus fault address register */
+#define NVIC_AFAULTS_OFFSET 0x0d3c /* Auxiliary fault status register */
+#define NVIC_PFR0_OFFSET 0x0d40 /* Processor feature register 0 */
+#define NVIC_PFR1_OFFSET 0x0d44 /* Processor feature register 1 */
+#define NVIC_DFR0_OFFSET 0x0d48 /* Debug feature register 0 */
+#define NVIC_AFR0_OFFSET 0x0d4c /* Auxiliary feature register 0 */
+#define NVIC_MMFR0_OFFSET 0x0d50 /* Memory model feature register 0 */
+#define NVIC_MMFR1_OFFSET 0x0d54 /* Memory model feature register 1 */
+#define NVIC_MMFR2_OFFSET 0x0d58 /* Memory model feature register 2 */
+#define NVIC_MMFR3_OFFSET 0x0d5c /* Memory model feature register 3 */
+#define NVIC_ISAR0_OFFSET 0x0d60 /* ISA feature register 0 */
+#define NVIC_ISAR1_OFFSET 0x0d64 /* ISA feature register 1 */
+#define NVIC_ISAR2_OFFSET 0x0d68 /* ISA feature register 2 */
+#define NVIC_ISAR3_OFFSET 0x0d6c /* ISA feature register 3 */
+#define NVIC_ISAR4_OFFSET 0x0d70 /* ISA feature register 4 */
+#define NVIC_CPACR_OFFSET 0x0d88 /* Coprocessor Access Control Register */
+#define NVIC_DHCSR_OFFSET 0x0df0 /* Debug Halting Control and Status Register */
+#define NVIC_DCRSR_OFFSET 0x0df4 /* Debug Core Register Selector Register */
+#define NVIC_DCRDR_OFFSET 0x0df8 /* Debug Core Register Data Register */
+#define NVIC_DEMCR_OFFSET 0x0dfc /* Debug Exception and Monitor Control Register */
+#define NVIC_STIR_OFFSET 0x0f00 /* Software trigger interrupt register */
+#define NVIC_FPCCR_OFFSET 0x0f34 /* Floating-point Context Control Register */
+#define NVIC_FPCAR_OFFSET 0x0f38 /* Floating-point Context Address Register */
+#define NVIC_FPDSCR_OFFSET 0x0f3c /* Floating-point Default Status Control Register */
+#define NVIC_MVFR0_OFFSET 0x0f40 /* Media and VFP Feature Register 0 */
+#define NVIC_MVFR1_OFFSET 0x0f44 /* Media and VFP Feature Register 1 */
+#define NVIC_PID4_OFFSET 0x0fd0 /* Peripheral identification register (PID4) */
+#define NVIC_PID5_OFFSET 0x0fd4 /* Peripheral identification register (PID5) */
+#define NVIC_PID6_OFFSET 0x0fd8 /* Peripheral identification register (PID6) */
+#define NVIC_PID7_OFFSET 0x0fdc /* Peripheral identification register (PID7) */
+#define NVIC_PID0_OFFSET 0x0fe0 /* Peripheral identification register bits 7:0 (PID0) */
+#define NVIC_PID1_OFFSET 0x0fe4 /* Peripheral identification register bits 15:8 (PID1) */
+#define NVIC_PID2_OFFSET 0x0fe8 /* Peripheral identification register bits 23:16 (PID2) */
+#define NVIC_PID3_OFFSET 0x0fec /* Peripheral identification register bits 23:16 (PID3) */
+#define NVIC_CID0_OFFSET 0x0ff0 /* Component identification register bits 7:0 (CID0) */
+#define NVIC_CID1_OFFSET 0x0ff4 /* Component identification register bits 15:8 (CID0) */
+#define NVIC_CID2_OFFSET 0x0ff8 /* Component identification register bits 23:16 (CID0) */
+#define NVIC_CID3_OFFSET 0x0ffc /* Component identification register bits 23:16 (CID0) */
+
+/* NVIC register addresses ******************************************************************/
+
+#define NVIC_ICTR (ARMV7M_NVIC_BASE + NVIC_ICTR_OFFSET)
+#define NVIC_SYSTICK_CTRL (ARMV7M_NVIC_BASE + NVIC_SYSTICK_CTRL_OFFSET)
+#define NVIC_SYSTICK_RELOAD (ARMV7M_NVIC_BASE + NVIC_SYSTICK_RELOAD_OFFSET)
+#define NVIC_SYSTICK_CURRENT (ARMV7M_NVIC_BASE + NVIC_SYSTICK_CURRENT_OFFSET)
+#define NVIC_SYSTICK_CALIB (ARMV7M_NVIC_BASE + NVIC_SYSTICK_CALIB_OFFSET)
+
+#define NVIC_IRQ_ENABLE(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_ENABLE_OFFSET(n))
+#define NVIC_IRQ0_31_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_ENABLE_OFFSET)
+#define NVIC_IRQ32_63_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_ENABLE_OFFSET)
+#define NVIC_IRQ64_95_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_ENABLE_OFFSET)
+#define NVIC_IRQ96_127_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_ENABLE_OFFSET)
+#define NVIC_IRQ128_159_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_ENABLE_OFFSET)
+#define NVIC_IRQ160_191_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_ENABLE_OFFSET)
+#define NVIC_IRQ192_223_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_ENABLE_OFFSET)
+#define NVIC_IRQ224_239_ENABLE (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_ENABLE_OFFSET)
+
+#define NVIC_IRQ_CLEAR(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_CLEAR_OFFSET(n))
+#define NVIC_IRQ0_31_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_CLEAR_OFFSET)
+#define NVIC_IRQ32_63_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_CLEAR_OFFSET)
+#define NVIC_IRQ64_95_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_CLEAR_OFFSET)
+#define NVIC_IRQ96_127_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_CLEAR_OFFSET)
+#define NVIC_IRQ128_159_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_CLEAR_OFFSET)
+#define NVIC_IRQ160_191_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_CLEAR_OFFSET)
+#define NVIC_IRQ192_223_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_CLEAR_OFFSET)
+#define NVIC_IRQ224_239_CLEAR (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_CLEAR_OFFSET)
+
+#define NVIC_IRQ_PEND(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_PEND_OFFSET(n))
+#define NVIC_IRQ0_31_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_PEND_OFFSET)
+#define NVIC_IRQ32_63_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_PEND_OFFSET)
+#define NVIC_IRQ64_95_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_PEND_OFFSET)
+#define NVIC_IRQ96_127_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_PEND_OFFSET)
+#define NVIC_IRQ128_159_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_PEND_OFFSET)
+#define NVIC_IRQ160_191_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_PEND_OFFSET)
+#define NVIC_IRQ192_223_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_PEND_OFFSET)
+#define NVIC_IRQ224_239_PEND (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_PEND_OFFSET)
+
+#define NVIC_IRQ_CLRPEND(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_CLRPEND_OFFSET(n))
+#define NVIC_IRQ0_31_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_CLRPEND_OFFSET)
+#define NVIC_IRQ32_63_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_CLRPEND_OFFSET)
+#define NVIC_IRQ64_95_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_CLRPEND_OFFSET)
+#define NVIC_IRQ96_127_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_CLRPEND_OFFSET)
+#define NVIC_IRQ128_159_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_CLRPEND_OFFSET)
+#define NVIC_IRQ160_191_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_CLRPEND_OFFSET)
+#define NVIC_IRQ192_223_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_CLRPEND_OFFSET)
+#define NVIC_IRQ224_239_CLRPEND (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_CLRPEND_OFFSET)
+
+#define NVIC_IRQ_ACTIVE(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_ACTIVE_OFFSET(n))
+#define NVIC_IRQ0_31_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ0_31_ACTIVE_OFFSET)
+#define NVIC_IRQ32_63_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ32_63_ACTIVE_OFFSET)
+#define NVIC_IRQ64_95_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ64_95_ACTIVE_OFFSET)
+#define NVIC_IRQ96_127_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ96_127_ACTIVE_OFFSET)
+#define NVIC_IRQ128_159_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ128_159_ACTIVE_OFFSET)
+#define NVIC_IRQ160_191_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ160_191_ACTIVE_OFFSET)
+#define NVIC_IRQ192_223_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ192_223_ACTIVE_OFFSET)
+#define NVIC_IRQ224_239_ACTIVE (ARMV7M_NVIC_BASE + NVIC_IRQ224_239_ACTIVE_OFFSET)
+
+#define NVIC_IRQ_PRIORITY(n) (ARMV7M_NVIC_BASE + NVIC_IRQ_PRIORITY_OFFSET(n))
+#define NVIC_IRQ0_3_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ0_3_PRIORITY_OFFSET)
+#define NVIC_IRQ4_7_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ4_7_PRIORITY_OFFSET)
+#define NVIC_IRQ8_11_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ8_11_PRIORITY_OFFSET)
+#define NVIC_IRQ12_15_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ12_15_PRIORITY_OFFSET)
+#define NVIC_IRQ16_19_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ16_19_PRIORITY_OFFSET)
+#define NVIC_IRQ20_23_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ20_23_PRIORITY_OFFSET)
+#define NVIC_IRQ24_27_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ24_27_PRIORITY_OFFSET)
+#define NVIC_IRQ28_31_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ28_31_PRIORITY_OFFSET)
+#define NVIC_IRQ32_35_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ32_35_PRIORITY_OFFSET)
+#define NVIC_IRQ36_39_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ36_39_PRIORITY_OFFSET)
+#define NVIC_IRQ40_43_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ40_43_PRIORITY_OFFSET)
+#define NVIC_IRQ44_47_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ44_47_PRIORITY_OFFSET)
+#define NVIC_IRQ48_51_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ48_51_PRIORITY_OFFSET)
+#define NVIC_IRQ52_55_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ52_55_PRIORITY_OFFSET)
+#define NVIC_IRQ56_59_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ56_59_PRIORITY_OFFSET)
+#define NVIC_IRQ60_63_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ60_63_PRIORITY_OFFSET)
+#define NVIC_IRQ64_67_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ64_67_PRIORITY_OFFSET)
+#define NVIC_IRQ68_71_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ68_71_PRIORITY_OFFSET)
+#define NVIC_IRQ72_75_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ72_75_PRIORITY_OFFSET)
+#define NVIC_IRQ76_79_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ76_79_PRIORITY_OFFSET)
+#define NVIC_IRQ80_83_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ80_83_PRIORITY_OFFSET)
+#define NVIC_IRQ84_87_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ84_87_PRIORITY_OFFSET)
+#define NVIC_IRQ88_91_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ88_91_PRIORITY_OFFSET)
+#define NVIC_IRQ92_95_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ92_95_PRIORITY_OFFSET)
+#define NVIC_IRQ96_99_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ96_99_PRIORITY_OFFSET)
+#define NVIC_IRQ100_103_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ100_103_PRIORITY_OFFSET)
+#define NVIC_IRQ104_107_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ104_107_PRIORITY_OFFSET)
+#define NVIC_IRQ108_111_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ108_111_PRIORITY_OFFSET)
+#define NVIC_IRQ112_115_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ112_115_PRIORITY_OFFSET)
+#define NVIC_IRQ116_119_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ116_119_PRIORITY_OFFSET)
+#define NVIC_IRQ120_123_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ120_123_PRIORITY_OFFSET)
+#define NVIC_IRQ124_127_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ124_127_PRIORITY_OFFSET)
+#define NVIC_IRQ128_131_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ128_131_PRIORITY_OFFSET)
+#define NVIC_IRQ132_135_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ132_135_PRIORITY_OFFSET)
+#define NVIC_IRQ136_139_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ136_139_PRIORITY_OFFSET)
+#define NVIC_IRQ140_143_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ140_143_PRIORITY_OFFSET)
+#define NVIC_IRQ144_147_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ144_147_PRIORITY_OFFSET)
+#define NVIC_IRQ148_151_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ148_151_PRIORITY_OFFSET)
+#define NVIC_IRQ152_155_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ152_155_PRIORITY_OFFSET)
+#define NVIC_IRQ156_159_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ156_159_PRIORITY_OFFSET)
+#define NVIC_IRQ160_163_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ160_163_PRIORITY_OFFSET)
+#define NVIC_IRQ164_167_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ164_167_PRIORITY_OFFSET)
+#define NVIC_IRQ168_171_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ168_171_PRIORITY_OFFSET)
+#define NVIC_IRQ172_175_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ172_175_PRIORITY_OFFSET)
+#define NVIC_IRQ176_179_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ176_179_PRIORITY_OFFSET)
+#define NVIC_IRQ180_183_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ180_183_PRIORITY_OFFSET)
+#define NVIC_IRQ184_187_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ184_187_PRIORITY_OFFSET)
+#define NVIC_IRQ188_191_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ188_191_PRIORITY_OFFSET)
+#define NVIC_IRQ192_195_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ192_195_PRIORITY_OFFSET)
+#define NVIC_IRQ196_199_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ196_199_PRIORITY_OFFSET)
+#define NVIC_IRQ200_203_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ200_203_PRIORITY_OFFSET)
+#define NVIC_IRQ204_207_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ204_207_PRIORITY_OFFSET)
+#define NVIC_IRQ208_211_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ208_211_PRIORITY_OFFSET)
+#define NVIC_IRQ212_215_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ212_215_PRIORITY_OFFSET)
+#define NVIC_IRQ216_219_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ216_219_PRIORITY_OFFSET)
+#define NVIC_IRQ220_223_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ220_223_PRIORITY_OFFSET)
+#define NVIC_IRQ224_227_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ224_227_PRIORITY_OFFSET)
+#define NVIC_IRQ228_231_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ228_231_PRIORITY_OFFSET)
+#define NVIC_IRQ232_235_PRIORITY (ARMV7M_NVIC_BASE + NVIC_IRQ232_235_PRIORITY_OFFSET)
+
+#define NVIC_CPUID_BASE (ARMV7M_NVIC_BASE + NVIC_CPUID_BASE_OFFSET)
+#define NVIC_INTCTRL (ARMV7M_NVIC_BASE + NVIC_INTCTRL_OFFSET)
+#define NVIC_VECTAB (ARMV7M_NVIC_BASE + NVIC_VECTAB_OFFSET)
+#define NVIC_AIRC (ARMV7M_NVIC_BASE + NVIC_AIRC_OFFSET)
+#define NVIC_SYSCON (ARMV7M_NVIC_BASE + NVIC_SYSCON_OFFSET)
+#define NVIC_CFGCON (ARMV7M_NVIC_BASE + NVIC_CFGCON_OFFSET)
+#define NVIC_SYSH_PRIORITY(n) (ARMV7M_NVIC_BASE + NVIC_SYSH_PRIORITY_OFFSET(n))
+#define NVIC_SYSH4_7_PRIORITY (ARMV7M_NVIC_BASE + NVIC_SYSH4_7_PRIORITY_OFFSET)
+#define NVIC_SYSH8_11_PRIORITY (ARMV7M_NVIC_BASE + NVIC_SYSH8_11_PRIORITY_OFFSET)
+#define NVIC_SYSH12_15_PRIORITY (ARMV7M_NVIC_BASE + NVIC_SYSH12_15_PRIORITY_OFFSET)
+#define NVIC_SYSHCON (ARMV7M_NVIC_BASE + NVIC_SYSHCON_OFFSET)
+#define NVIC_CFAULTS (ARMV7M_NVIC_BASE + NVIC_CFAULTS_OFFSET)
+#define NVIC_HFAULTS (ARMV7M_NVIC_BASE + NVIC_HFAULTS_OFFSET)
+#define NVIC_DFAULTS (ARMV7M_NVIC_BASE + NVIC_DFAULTS_OFFSET)
+#define NVIC_MEMMANAGE_ADDR (ARMV7M_NVIC_BASE + NVIC_MEMMANAGE_ADDR_OFFSET)
+#define NVIC_BFAULT_ADDR (ARMV7M_NVIC_BASE + NVIC_BFAULT_ADDR_OFFSET)
+#define NVIC_AFAULTS (ARMV7M_NVIC_BASE + NVIC_AFAULTS_OFFSET)
+#define NVIC_PFR0 (ARMV7M_NVIC_BASE + NVIC_PFR0_OFFSET)
+#define NVIC_PFR1 (ARMV7M_NVIC_BASE + NVIC_PFR1_OFFSET)
+#define NVIC_DFR0 (ARMV7M_NVIC_BASE + NVIC_DFR0_OFFSET)
+#define NVIC_AFR0 (ARMV7M_NVIC_BASE + NVIC_AFR0_OFFSET)
+#define NVIC_MMFR0 (ARMV7M_NVIC_BASE + NVIC_MMFR0_OFFSET)
+#define NVIC_MMFR1 (ARMV7M_NVIC_BASE + NVIC_MMFR1_OFFSET)
+#define NVIC_MMFR2 (ARMV7M_NVIC_BASE + NVIC_MMFR2_OFFSET)
+#define NVIC_MMFR3 (ARMV7M_NVIC_BASE + NVIC_MMFR3_OFFSET)
+#define NVIC_ISAR0 (ARMV7M_NVIC_BASE + NVIC_ISAR0_OFFSET)
+#define NVIC_ISAR1 (ARMV7M_NVIC_BASE + NVIC_ISAR1_OFFSET)
+#define NVIC_ISAR2 (ARMV7M_NVIC_BASE + NVIC_ISAR2_OFFSET)
+#define NVIC_ISAR3 (ARMV7M_NVIC_BASE + NVIC_ISAR3_OFFSET)
+#define NVIC_ISAR4 (ARMV7M_NVIC_BASE + NVIC_ISAR4_OFFSET)
+#define NVIC_CPACR (ARMV7M_NVIC_BASE + NVIC_CPACR_OFFSET)
+#define NVIC_DHCSR (ARMV7M_NVIC_BASE + NVIC_DHCSR_OFFSET)
+#define NVIC_DCRSR (ARMV7M_NVIC_BASE + NVIC_DCRSR_OFFSET)
+#define NVIC_DCRDR (ARMV7M_NVIC_BASE + NVIC_DCRDR_OFFSET)
+#define NVIC_DEMCR (ARMV7M_NVIC_BASE + NVIC_DEMCR_OFFSET)
+#define NVIC_STIR (ARMV7M_NVIC_BASE + NVIC_STIR_OFFSET)
+#define NVIC_FPCCR (ARMV7M_NVIC_BASE + NVIC_FPCCR_OFFSET)
+#define NVIC_PID4 (ARMV7M_NVIC_BASE + NVIC_PID4_OFFSET)
+#define NVIC_PID5 (ARMV7M_NVIC_BASE + NVIC_PID5_OFFSET)
+#define NVIC_PID6 (ARMV7M_NVIC_BASE + NVIC_PID6_OFFSET)
+#define NVIC_PID7 (ARMV7M_NVIC_BASE + NVIC_PID7_OFFSET)
+#define NVIC_PID0 (ARMV7M_NVIC_BASE + NVIC_PID0_OFFSET)
+#define NVIC_PID1 (ARMV7M_NVIC_BASE + NVIC_PID1_OFFSET)
+#define NVIC_PID2 (ARMV7M_NVIC_BASE + NVIC_PID2_OFFSET)
+#define NVIC_PID3 (ARMV7M_NVIC_BASE + NVIC_PID3_OFFSET)
+#define NVIC_CID0 (ARMV7M_NVIC_BASE + NVIC_CID0_OFFSET)
+#define NVIC_CID1 (ARMV7M_NVIC_BASE + NVIC_CID1_OFFSET)
+#define NVIC_CID2 (ARMV7M_NVIC_BASE + NVIC_CID2_OFFSET)
+#define NVIC_CID3 (ARMV7M_NVIC_BASE + NVIC_CID3_OFFSET)
+
+/* NVIC register bit definitions ************************************************************/
+
+/* Interrrupt controller type (INCTCTL_TYPE) */
+
+#define NVIC_ICTR_INTLINESNUM_SHIFT 0 /* Bits 4-0: Number of interrupt intputs / 32 */
+#define NVIC_ICTR_INTLINESNUM_MASK (0x1f << NVIC_ICTR_INTLINESNUM_SHIFT)
+
+/* SysTick control and status register (SYSTICK_CTRL) */
+
+#define NVIC_SYSTICK_CTRL_ENABLE (1 << 0) /* Bit 0: Enable */
+#define NVIC_SYSTICK_CTRL_TICKINT (1 << 1) /* Bit 1: Tick interrupt */
+#define NVIC_SYSTICK_CTRL_CLKSOURCE (1 << 2) /* Bit 2: Clock source */
+#define NVIC_SYSTICK_CTRL_COUNTFLAG (1 << 16) /* Bit 16: Count Flag */
+
+/* SysTick reload value register (SYSTICK_RELOAD) */
+
+#define NVIC_SYSTICK_RELOAD_SHIFT 0 /* Bits 23-0: Timer reload value */
+#define NVIC_SYSTICK_RELOAD_MASK (0x00ffffff << NVIC_SYSTICK_RELOAD_SHIFT)
+
+/* SysTick current value register (SYSTICK_CURRENT) */
+
+#define NVIC_SYSTICK_CURRENT_SHIFT 0 /* Bits 23-0: Timer current value */
+#define NVIC_SYSTICK_CURRENT_MASK (0x00ffffff << NVIC_SYSTICK_RELOAD_SHIFT)
+
+/* SysTick calibration value register (SYSTICK_CALIB) */
+
+#define NVIC_SYSTICK_CALIB_TENMS_SHIFT 0 /* Bits 23-0: Calibration value */
+#define NVIC_SYSTICK_CALIB_TENMS_MASK (0x00ffffff << NVIC_SYSTICK_CALIB_TENMS_SHIFT)
+#define NVIC_SYSTICK_CALIB_SKEW (1 << 30) /* Bit 30: Calibration value inexact */
+#define NVIC_SYSTICK_CALIB_NOREF (1 << 31) /* Bit 31: No external reference clock */
+
+/* Interrupt control state register (INTCTRL) */
+
+#define NVIC_INTCTRL_NMIPENDSET (1 << 31) /* Bit 31: Set pending NMI bit */
+#define NVIC_INTCTRL_PENDSVSET (1 << 28) /* Bit 28: Set pending PendSV bit */
+#define NVIC_INTCTRL_PENDSVCLR (1 << 27) /* Bit 27: Clear pending PendSV bit */
+#define NVIC_INTCTRL_PENDSTSET (1 << 26) /* Bit 26: Set pending SysTick bit */
+#define NVIC_INTCTRL_PENDSTCLR (1 << 25) /* Bit 25: Clear pending SysTick bit */
+#define NVIC_INTCTRL_ISPREEMPOT (1 << 23) /* Bit 23: Pending active next cycle */
+#define NVIC_INTCTRL_ISRPENDING (1 << 22) /* Bit 22: Interrupt pending flag */
+#define NVIC_INTCTRL_VECTPENDING_SHIFT 12 /* Bits 21-12: Pending ISR number field */
+#define NVIC_INTCTRL_VECTPENDING_MASK (0x3ff << NVIC_INTCTRL_VECTPENDING_SHIFT)
+#define NVIC_INTCTRL_RETTOBASE (1 << 11) /* Bit 11: no other exceptions pending */
+#define NVIC_INTCTRL_VECTACTIVE_SHIFT 0 /* Bits 8-0: Active ISR number */
+#define NVIC_INTCTRL_VECTACTIVE_MASK (0x1ff << NVIC_INTCTRL_VECTACTIVE_SHIFT)
+
+/* System control register (SYSCON) */
+
+ /* Bit 0: Reserved */
+#define NVIC_SYSCON_SLEEPONEXIT (1 << 1) /* Bit 1: Sleep-on-exit (returning from Handler to Thread mode) */
+#define NVIC_SYSCON_SLEEPDEEP (1 << 2) /* Bit 2: Use deep sleep in low power mode */
+ /* Bit 3: Reserved */
+#define NVIC_SYSCON_SEVONPEND (1 << 4) /* Bit 4: Send Event on Pending bit */
+ /* Bits 5-31: Reserved */
+
+/* System handler 4-7 priority register */
+
+#define NVIC_SYSH_PRIORITY_PR4_SHIFT 0
+#define NVIC_SYSH_PRIORITY_PR4_MASK (0xff << NVIC_SYSH_PRIORITY_PR4_SHIFT)
+#define NVIC_SYSH_PRIORITY_PR5_SHIFT 8
+#define NVIC_SYSH_PRIORITY_PR5_MASK (0xff << NVIC_SYSH_PRIORITY_PR5_SHIFT)
+#define NVIC_SYSH_PRIORITY_PR6_SHIFT 16
+#define NVIC_SYSH_PRIORITY_PR6_MASK (0xff << NVIC_SYSH_PRIORITY_PR6_SHIFT)
+#define NVIC_SYSH_PRIORITY_PR7_SHIFT 24
+#define NVIC_SYSH_PRIORITY_PR7_MASK (0xff << NVIC_SYSH_PRIORITY_PR7_SHIFT)
+
+/* System handler 8-11 priority register */
+
+#define NVIC_SYSH_PRIORITY_PR8_SHIFT 0
+#define NVIC_SYSH_PRIORITY_PR8_MASK (0xff << NVIC_SYSH_PRIORITY_PR8_SHIFT)
+#define NVIC_SYSH_PRIORITY_PR9_SHIFT 8
+#define NVIC_SYSH_PRIORITY_PR9_MASK (0xff << NVIC_SYSH_PRIORITY_PR9_SHIFT)
+#define NVIC_SYSH_PRIORITY_PR10_SHIFT 16
+#define NVIC_SYSH_PRIORITY_PR10_MASK (0xff << NVIC_SYSH_PRIORITY_PR10_SHIFT)
+#define NVIC_SYSH_PRIORITY_PR11_SHIFT 24
+#define NVIC_SYSH_PRIORITY_PR11_MASK (0xff << NVIC_SYSH_PRIORITY_PR11_SHIFT)
+
+/* System handler 12-15 priority register */
+
+#define NVIC_SYSH_PRIORITY_PR12_SHIFT 0
+#define NVIC_SYSH_PRIORITY_PR12_MASK (0xff << NVIC_SYSH_PRIORITY_PR12_SHIFT)
+#define NVIC_SYSH_PRIORITY_PR13_SHIFT 8
+#define NVIC_SYSH_PRIORITY_PR13_MASK (0xff << NVIC_SYSH_PRIORITY_PR13_SHIFT)
+#define NVIC_SYSH_PRIORITY_PR14_SHIFT 16
+#define NVIC_SYSH_PRIORITY_PR14_MASK (0xff << NVIC_SYSH_PRIORITY_PR14_SHIFT)
+#define NVIC_SYSH_PRIORITY_PR15_SHIFT 24
+#define NVIC_SYSH_PRIORITY_PR15_MASK (0xff << NVIC_SYSH_PRIORITY_PR15_SHIFT)
+
+/* System handler control and state register (SYSHCON) */
+
+#define NVIC_SYSHCON_MEMFAULTACT (1 << 0) /* Bit 0: MemManage is active */
+#define NVIC_SYSHCON_BUSFAULTACT (1 << 1) /* Bit 1: BusFault is active */
+#define NVIC_SYSHCON_USGFAULTACT (1 << 3) /* Bit 3: UsageFault is active */
+#define NVIC_SYSHCON_SVCALLACT (1 << 7) /* Bit 7: SVCall is active */
+#define NVIC_SYSHCON_MONITORACT (1 << 8) /* Bit 8: Monitor is active */
+#define NVIC_SYSHCON_PENDSVACT (1 << 10) /* Bit 10: PendSV is active */
+#define NVIC_SYSHCON_SYSTICKACT (1 << 11) /* Bit 11: SysTick is active */
+#define NVIC_SYSHCON_USGFAULTPENDED (1 << 12) /* Bit 12: Usage fault is pended */
+#define NVIC_SYSHCON_MEMFAULTPENDED (1 << 13) /* Bit 13: MemManage is pended */
+#define NVIC_SYSHCON_BUSFAULTPENDED (1 << 14) /* Bit 14: BusFault is pended */
+#define NVIC_SYSHCON_SVCALLPENDED (1 << 15) /* Bit 15: SVCall is pended */
+#define NVIC_SYSHCON_MEMFAULTENA (1 << 16) /* Bit 16: MemFault enabled */
+#define NVIC_SYSHCON_BUSFAULTENA (1 << 17) /* Bit 17: BusFault enabled */
+#define NVIC_SYSHCON_USGFAULTENA (1 << 18) /* Bit 18: UsageFault enabled */
+
+/* Debug Exception and Monitor Control Register (DEMCR) */
+
+#define NVIC_DEMCR_VCCORERESET (1 << 0) /* Bit 0: Reset Vector Catch */
+#define NVIC_DEMCR_VCMMERR (1 << 4) /* Bit 4: Debug trap on Memory Management faults */
+#define NVIC_DEMCR_VCNOCPERR (1 << 5) /* Bit 5: Debug trap on Usage Fault access to non-present coprocessor */
+#define NVIC_DEMCR_VCCHKERR (1 << 6) /* Bit 6: Debug trap on Usage Fault enabled checking errors */
+#define NVIC_DEMCR_VCSTATERR (1 << 7) /* Bit 7: Debug trap on Usage Fault state error */
+#define NVIC_DEMCR_VCBUSERR (1 << 8) /* Bit 8: Debug Trap on normal Bus error */
+#define NVIC_DEMCR_VCINTERR (1 << 9) /* Bit 9: Debug Trap on interrupt/exception service errors */
+#define NVIC_DEMCR_VCHARDERR (1 << 10) /* Bit 10: Debug trap on Hard Fault */
+#define NVIC_DEMCR_MONEN (1 << 16) /* Bit 16: Enable the debug monitor */
+#define NVIC_DEMCR_MONPEND (1 << 17) /* Bit 17: Pend the monitor to activate when priority permits */
+#define NVIC_DEMCR_MONSTEP (1 << 18) /* Bit 18: Steps the core */
+#define NVIC_DEMCR_MONREQ (1 << 19) /* Bit 19: Monitor wake-up mode */
+#define NVIC_DEMCR_TRCENA (1 << 24) /* Bit 24: Enable trace and debug blocks */
+
+/********************************************************************************************
+ * Public Types
+ ********************************************************************************************/
+
+/********************************************************************************************
+ * Public Data
+ ********************************************************************************************/
+
+/********************************************************************************************
+ * Public Function Prototypes
+ ********************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_COMMON_ARMV7_M_NVIC_H */
diff --git a/nuttx/arch/arm/src/armv7-m/psr.h b/nuttx/arch/arm/src/armv7-m/psr.h
new file mode 100644
index 000000000..30913f7c9
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/psr.h
@@ -0,0 +1,87 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/psr.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_COMMON_ARMV7_M_PSR_H
+#define __ARCH_ARM_SRC_COMMON_ARMV7_M_PSR_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Application Program Status Register (APSR) */
+
+#define ARMV7M_APSR_Q (1 << 27) /* Bit 27: Sticky saturation flag */
+#define ARMV7M_APSR_V (1 << 28) /* Bit 28: Overflow flag */
+#define ARMV7M_APSR_C (1 << 29) /* Bit 29: Carry/borrow flag */
+#define ARMV7M_APSR_Z (1 << 30) /* Bit 30: Zero flag */
+#define ARMV7M_APSR_N (1 << 31) /* Bit 31: Negative, less than flag */
+
+/* Interrupt Program Status Register (IPSR) */
+
+#define ARMV7M_IPSR_ISR_SHIFT 0 /* Bits 8-0: ISR number */
+#define ARMV7M_IPSR_ISR_MASK (0x1ff << ARMV7M_IPSR_ISR_SHIFT)
+
+/* Execution PSR Register (EPSR) */
+
+#define ARMV7M_EPSR_ICIIT1_SHIFT 10 /* Bits 15-10: Interrupt-Continuable-Instruction/If-Then bits */
+#define ARMV7M_EPSR_ICIIT1_MASK (3 << ARMV7M_EPSR_ICIIT1_SHIFT)
+#define ARMV7M_EPSR_T (1 << 24) /* Bit 24: T-bit */
+#define ARMV7M_EPSR_ICIIT2_SHIFT 25 /* Bits 26-25: Interrupt-Continuable-Instruction/If-Then bits */
+#define ARMV7M_EPSR_ICIIT2_MASK (3 << ARMV7M_EPSR_ICIIT2_SHIFT)
+
+/* Save xPSR bits */
+
+#define ARMV7M_XPSR_ISR_SHIFT ARMV7M_IPSR_ISR_SHIFT
+#define ARMV7M_XPSR_ISR_MASK ARMV7M_IPSR_ISR_MASK
+#define ARMV7M_XPSR_ICIIT1_SHIFT ARMV7M_EPSR_ICIIT1_SHIFT/
+#define ARMV7M_XPSR_ICIIT1_MASK ARMV7M_EPSR_ICIIT1_MASK
+#define ARMV7M_XPSR_T ARMV7M_EPSR_T
+#define ARMV7M_XPSR_ICIIT2_SHIFT ARMV7M_EPSR_ICIIT2_SHIFT
+#define ARMV7M_XPSR_ICIIT2_MASK ARMV7M_EPSR_ICIIT2_MASK
+#define ARMV7M_XPSR_Q ARMV7M_APSR_Q
+#define ARMV7M_XPSR_V ARMV7M_APSR_V
+#define ARMV7M_XPSR_C ARMV7M_APSR_C
+#define ARMV7M_XPSR_Z ARMV7M_APSR_Z
+#define ARMV7M_XPSR_N ARMV7M_APSR_N
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_COMMON_ARMV7_M_PSR_H */
diff --git a/nuttx/arch/arm/src/armv7-m/svcall.h b/nuttx/arch/arm/src/armv7-m/svcall.h
new file mode 100644
index 000000000..51b5b9111
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/svcall.h
@@ -0,0 +1,94 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/svcall.h
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_COMMON_CORTEXM_SVCALL_H
+#define __ARCH_ARM_SRC_COMMON_CORTEXM_SVCALL_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_NUTTX_KERNEL
+# include <syscall.h>
+#endif
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Configuration ********************************************************************/
+/* This logic uses three system calls {0,1,2} for context switching. The first three
+ * syscall values must be reserved.
+ */
+
+#ifdef CONFIG_NUTTX_KERNEL
+# ifndef CONFIG_SYS_RESERVED
+# error "CONFIG_SYS_RESERVED must be defined to the value 3"
+# elif CONFIG_SYS_RESERVED != 3
+# error "CONFIG_SYS_RESERVED must have the value 3"
+# endif
+#endif
+
+/* Cortex M3 system calls ***********************************************************/
+
+/* SYS call 0:
+ *
+ * int up_saveusercontext(uint32_t *saveregs);
+ */
+
+#define SYS_save_context (0)
+
+/* SYS call 1:
+ *
+ * void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn));
+ */
+
+#define SYS_restore_context (1)
+
+/* SYS call 2:
+ *
+ * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
+ */
+
+#define SYS_switch_context (2)
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_COMMON_CORTEXM_SVCALL_H */
+
diff --git a/nuttx/arch/arm/src/armv7-m/up_assert.c b/nuttx/arch/arm/src/armv7-m/up_assert.c
new file mode 100644
index 000000000..77fd0b596
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_assert.c
@@ -0,0 +1,334 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_assert.c
+ *
+ * Copyright (C) 2009-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <stdlib.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Output debug info if stack dump is selected -- even if
+ * debug is not selected.
+ */
+
+#ifdef CONFIG_ARCH_STACKDUMP
+# undef lldbg
+# define lldbg lib_lowprintf
+#endif
+
+/* The following is just intended to keep some ugliness out of the mainline
+ * code. We are going to print the task name if:
+ *
+ * CONFIG_TASK_NAME_SIZE > 0 && <-- The task has a name
+ * (defined(CONFIG_DEBUG) || <-- And the debug is enabled (lldbg used)
+ * defined(CONFIG_ARCH_STACKDUMP) <-- Or lib_lowprintf() is used
+ */
+
+#undef CONFIG_PRINT_TASKNAME
+#if CONFIG_TASK_NAME_SIZE > 0 && (defined(CONFIG_DEBUG) || defined(CONFIG_ARCH_STACKDUMP))
+# define CONFIG_PRINT_TASKNAME 1
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_getsp
+ ****************************************************************************/
+
+/* I don't know if the builtin to get SP is enabled */
+
+static inline uint32_t up_getsp(void)
+{
+ uint32_t sp;
+ __asm__
+ (
+ "\tmov %0, sp\n\t"
+ : "=r"(sp)
+ );
+ return sp;
+}
+
+/****************************************************************************
+ * Name: up_stackdump
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_STACKDUMP
+static void up_stackdump(uint32_t sp, uint32_t stack_base)
+{
+ uint32_t stack ;
+
+ for (stack = sp & ~0x1f; stack < stack_base; stack += 32)
+ {
+ uint32_t *ptr = (uint32_t*)stack;
+ lldbg("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ stack, ptr[0], ptr[1], ptr[2], ptr[3],
+ ptr[4], ptr[5], ptr[6], ptr[7]);
+ }
+}
+#else
+# define up_stackdump()
+#endif
+
+/****************************************************************************
+ * Name: up_registerdump
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_STACKDUMP
+static inline void up_registerdump(void)
+{
+ /* Are user registers available from interrupt processing? */
+
+ if (current_regs)
+ {
+ /* Yes.. dump the interrupt registers */
+
+ lldbg("R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ current_regs[REG_R0], current_regs[REG_R1],
+ current_regs[REG_R2], current_regs[REG_R3],
+ current_regs[REG_R4], current_regs[REG_R5],
+ current_regs[REG_R6], current_regs[REG_R7]);
+ lldbg("R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ current_regs[REG_R8], current_regs[REG_R9],
+ current_regs[REG_R10], current_regs[REG_R11],
+ current_regs[REG_R12], current_regs[REG_R13],
+ current_regs[REG_R14], current_regs[REG_R15]);
+ lldbg("xPSR: %08x PRIMASK: %08x\n",
+ current_regs[REG_XPSR], current_regs[REG_PRIMASK]);
+ }
+}
+#else
+# define up_registerdump()
+#endif
+
+/****************************************************************************
+ * Name: up_dumpstate
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_STACKDUMP
+static void up_dumpstate(void)
+{
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+ uint32_t sp = up_getsp();
+ uint32_t ustackbase;
+ uint32_t ustacksize;
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ uint32_t istackbase;
+ uint32_t istacksize;
+#endif
+
+ /* Get the limits on the user stack memory */
+
+ if (rtcb->pid == 0)
+ {
+ ustackbase = g_heapbase - 4;
+ ustacksize = CONFIG_IDLETHREAD_STACKSIZE;
+ }
+ else
+ {
+ ustackbase = (uint32_t)rtcb->adj_stack_ptr;
+ ustacksize = (uint32_t)rtcb->adj_stack_size;
+ }
+
+ /* Get the limits on the interrupt stack memory */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ istackbase = (uint32_t)&g_intstackbase;
+ istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4;
+
+ /* Show interrupt stack info */
+
+ lldbg("sp: %08x\n", sp);
+ lldbg("IRQ stack:\n");
+ lldbg(" base: %08x\n", istackbase);
+ lldbg(" size: %08x\n", istacksize);
+
+ /* Does the current stack pointer lie within the interrupt
+ * stack?
+ */
+
+ if (sp <= istackbase && sp > istackbase - istacksize)
+ {
+ /* Yes.. dump the interrupt stack */
+
+ up_stackdump(sp, istackbase);
+ }
+
+ /* Extract the user stack pointer if we are in an interrupt handler.
+ * If we are not in an interrupt handler. Then sp is the user stack
+ * pointer (and the above range check should have failed).
+ */
+
+ if (current_regs)
+ {
+ sp = current_regs[REG_R13];
+ lldbg("sp: %08x\n", sp);
+ }
+
+ lldbg("User stack:\n");
+ lldbg(" base: %08x\n", ustackbase);
+ lldbg(" size: %08x\n", ustacksize);
+
+ /* Dump the user stack if the stack pointer lies within the allocated user
+ * stack memory.
+ */
+
+ if (sp <= ustackbase && sp > ustackbase - ustacksize)
+ {
+ up_stackdump(sp, ustackbase);
+ }
+#else
+ lldbg("sp: %08x\n", sp);
+ lldbg("stack base: %08x\n", ustackbase);
+ lldbg("stack size: %08x\n", ustacksize);
+
+ /* Dump the user stack if the stack pointer lies within the allocated user
+ * stack memory.
+ */
+
+ if (sp > ustackbase || sp <= ustackbase - ustacksize)
+ {
+ lldbg("ERROR: Stack pointer is not within allocated stack\n");
+ }
+ else
+ {
+ up_stackdump(sp, ustackbase);
+ }
+#endif
+
+ /* Then dump the registers (if available) */
+
+ up_registerdump();
+}
+#else
+# define up_dumpstate()
+#endif
+
+/****************************************************************************
+ * Name: _up_assert
+ ****************************************************************************/
+
+static void _up_assert(int errorcode) /* __attribute__ ((noreturn)) */
+{
+ /* Are we in an interrupt handler or the idle task? */
+
+ if (current_regs || ((_TCB*)g_readytorun.head)->pid == 0)
+ {
+ (void)irqsave();
+ for(;;)
+ {
+#ifdef CONFIG_ARCH_LEDS
+ up_ledon(LED_PANIC);
+ up_mdelay(250);
+ up_ledoff(LED_PANIC);
+ up_mdelay(250);
+#endif
+ }
+ }
+ else
+ {
+ exit(errorcode);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_assert
+ ****************************************************************************/
+
+void up_assert(const uint8_t *filename, int lineno)
+{
+#ifdef CONFIG_PRINT_TASKNAME
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+#endif
+
+ up_ledon(LED_ASSERTION);
+#ifdef CONFIG_PRINT_TASKNAME
+ lldbg("Assertion failed at file:%s line: %d task: %s\n",
+ filename, lineno, rtcb->name);
+#else
+ lldbg("Assertion failed at file:%s line: %d\n",
+ filename, lineno);
+#endif
+ up_dumpstate();
+ _up_assert(EXIT_FAILURE);
+}
+
+/****************************************************************************
+ * Name: up_assert_code
+ ****************************************************************************/
+
+void up_assert_code(const uint8_t *filename, int lineno, int errorcode)
+{
+#ifdef CONFIG_PRINT_TASKNAME
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+#endif
+
+ up_ledon(LED_ASSERTION);
+#ifdef CONFIG_PRINT_TASKNAME
+ lldbg("Assertion failed at file:%s line: %d task: %s error code: %d\n",
+ filename, lineno, rtcb->name, errorcode);
+#else
+ lldbg("Assertion failed at file:%s line: %d error code: %d\n",
+ filename, lineno, errorcode);
+#endif
+ up_dumpstate();
+ _up_assert(errorcode);
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_blocktask.c b/nuttx/arch/arm/src/armv7-m/up_blocktask.c
new file mode 100755
index 000000000..896476ed2
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_blocktask.c
@@ -0,0 +1,167 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_blocktask.c
+ *
+ * Copyright (C) 2007-2009, 2012 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 <stdbool.h>
+#include <sched.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_block_task
+ *
+ * Description:
+ * The currently executing task at the head of
+ * the ready to run list must be stopped. Save its context
+ * and move it to the inactive list specified by task_state.
+ *
+ * Inputs:
+ * tcb: Refers to a task in the ready-to-run list (normally
+ * the task at the head of the list). It most be
+ * stopped, its context saved and moved into one of the
+ * waiting task lists. It it was the task at the head
+ * of the ready-to-run list, then a context to the new
+ * ready to run task must be performed.
+ * task_state: Specifies which waiting task list should be
+ * hold the blocked task TCB.
+ *
+ ****************************************************************************/
+
+void up_block_task(_TCB *tcb, tstate_t task_state)
+{
+ /* Verify that the context switch can be performed */
+
+ if ((tcb->task_state < FIRST_READY_TO_RUN_STATE) ||
+ (tcb->task_state > LAST_READY_TO_RUN_STATE))
+ {
+ PANIC(OSERR_BADBLOCKSTATE);
+ }
+ else
+ {
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+ bool switch_needed;
+
+ /* Remove the tcb task from the ready-to-run list. If we
+ * are blocking the task at the head of the task list (the
+ * most likely case), then a context switch to the next
+ * ready-to-run task is needed. In this case, it should
+ * also be true that rtcb == tcb.
+ */
+
+ switch_needed = sched_removereadytorun(tcb);
+
+ /* Add the task to the specified blocked task list */
+
+ sched_addblocked(tcb, (tstate_t)task_state);
+
+ /* If there are any pending tasks, then add them to the g_readytorun
+ * task list now
+ */
+
+ if (g_pendingtasks.head)
+ {
+ switch_needed |= sched_mergepending();
+ }
+
+ /* Now, perform the context switch if one is needed */
+
+ if (switch_needed)
+ {
+ /* Are we in an interrupt handler? */
+
+ if (current_regs)
+ {
+ /* Yes, then we have to do things differently.
+ * Just copy the current_regs into the OLD rtcb.
+ */
+
+ up_savestate(rtcb->xcp.regs);
+
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+
+ /* Then switch contexts */
+
+ up_restorestate(rtcb->xcp.regs);
+ }
+
+ /* No, then we will need to perform the user context switch */
+
+ else
+ {
+ /* Switch context to the context of the task at the head of the
+ * ready to run list.
+ */
+
+ _TCB *nexttcb = (_TCB*)g_readytorun.head;
+ up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+
+ /* up_switchcontext forces a context switch to the task at the
+ * head of the ready-to-run list. It does not 'return' in the
+ * normal sense. When it does return, it is because the blocked
+ * task is again ready to run and has execution priority.
+ */
+ }
+ }
+ }
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_copystate.c b/nuttx/arch/arm/src/armv7-m/up_copystate.c
new file mode 100644
index 000000000..a5ad312f5
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_copystate.c
@@ -0,0 +1,86 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_copystate.c
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_copystate
+ ****************************************************************************/
+
+/* A little faster than most memcpy's */
+
+void up_copystate(uint32_t *dest, uint32_t *src)
+{
+ int i;
+
+ /* In the Cortex-M3 model, the state is copied from the stack to the TCB,
+ * but only a reference is passed to get the state from the TCB. So the
+ * following check avoids copying the TCB save area onto itself:
+ */
+
+ if (src != dest)
+ {
+ for (i = 0; i < XCPTCONTEXT_REGS; i++)
+ {
+ *dest++ = *src++;
+ }
+ }
+}
+
diff --git a/nuttx/arch/arm/src/armv7-m/up_doirq.c b/nuttx/arch/arm/src/armv7-m/up_doirq.c
new file mode 100644
index 000000000..7ac1ec34d
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_doirq.c
@@ -0,0 +1,123 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_doirq.c
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <assert.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+uint32_t *up_doirq(int irq, uint32_t *regs)
+{
+ up_ledon(LED_INIRQ);
+#ifdef CONFIG_SUPPRESS_INTERRUPTS
+ PANIC(OSERR_ERREXCEPTION);
+#else
+ uint32_t *savestate;
+
+ /* Nested interrupts are not supported in this implementation. If you want
+ * implemented nested interrupts, you would have to (1) change the way that
+ * current regs is handled and (2) the design associated with
+ * CONFIG_ARCH_INTERRUPTSTACK.
+ */
+
+ /* Current regs non-zero indicates that we are processing an interrupt;
+ * current_regs is also used to manage interrupt level context switches.
+ */
+
+ savestate = (uint32_t*)current_regs;
+ current_regs = regs;
+
+ /* Mask and acknowledge the interrupt */
+
+ up_maskack_irq(irq);
+
+ /* Deliver the IRQ */
+
+ irq_dispatch(irq, regs);
+
+ /* If a context switch occurred while processing the interrupt then
+ * current_regs may have change value. If we return any value different
+ * from the input regs, then the lower level will know that a context
+ * switch occurred during interrupt processing.
+ */
+
+ regs = (uint32_t*)current_regs;
+
+ /* Restore the previous value of current_regs. NULL would indicate that
+ * we are no longer in an interrupt handler. It will be non-NULL if we
+ * are returning from a nested interrupt.
+ */
+
+ current_regs = savestate;
+
+ /* Unmask the last interrupt (global interrupts are still disabled) */
+
+ up_enable_irq(irq);
+#endif
+ up_ledoff(LED_INIRQ);
+ return regs;
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_exception.S b/nuttx/arch/arm/src/armv7-m/up_exception.S
new file mode 100644
index 000000000..31d8dbb0c
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_exception.S
@@ -0,0 +1,237 @@
+/************************************************************************************
+ * arch/arm/src/stm32/up_exception.S
+ * arch/arm/src/chip/up_exception.S
+ *
+ * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012 Michael Smith. 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 <arch/irq.h>
+#include "exc_return.h"
+
+#include "chip.h"
+
+/************************************************************************************
+ * Global Symbols
+ ************************************************************************************/
+
+ .globl exception_common
+
+ .syntax unified
+ .thumb
+ .file "up_exception.S"
+
+/************************************************************************************
+ * .text
+ ************************************************************************************/
+
+/* Common exception handling logic. On entry here, the return stack is on either
+ * the PSP or the MSP and looks like the following:
+ *
+ * REG_XPSR
+ * REG_R15
+ * REG_R14
+ * REG_R12
+ * REG_R3
+ * REG_R2
+ * REG_R1
+ * MSP->REG_R0
+ *
+ * And
+ * IPSR contains the IRQ number
+ * R14 Contains the EXC_RETURN value
+ * We are in handler mode and the current SP is the MSP
+ *
+ * If CONFIG_ARCH_FPU is defined, the volatile FP registers and FPSCR are on the
+ * return stack immediately above REG_XPSR.
+ */
+
+ .text
+ .type exception_common, function
+ .thumb_func
+exception_common:
+
+ mrs r0, ipsr /* R0=exception number */
+
+ /* Complete the context save */
+
+ /* The EXC_RETURN value tells us whether the context is on the MSP or PSP */
+
+ tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
+ ite eq /* next two instructions conditional */
+ mrseq r1, msp /* R1=The main stack pointer */
+ mrsne r1, psp /* R1=The process stack pointer */
+
+ mov r2, r1 /* R2=Copy of the main/process stack pointer */
+ add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
+ /* (ignoring the xPSR[9] alignment bit) */
+ mrs r3, primask /* R3=Current PRIMASK setting */
+
+#ifdef CONFIG_ARCH_FPU
+
+ /* Save the non-volatile FP registers here.
+ *
+ * This routine is the only point where we can save these registers; either before
+ * or after calling up_doirq. The compiler is free to use them at any time as long
+ * as they are restored before returning, so we can't assume that we can get at the
+ * true values of these registers in any routine called from here.
+ *
+ * XXX we could do all this saving lazily on the context switch side if we knew where to put
+ * the registers.
+ */
+
+ vstmdb r1!, {s16-s31} /* Save the non-volatile FP context */
+
+#endif
+
+ stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP/PRIMASK values */
+
+ /* Disable interrupts, select the stack to use for interrupt handling
+ * and call up_doirq to handle the interrupt
+ */
+
+ cpsid i /* Disable further interrupts */
+
+ /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt
+ * stack pointer. The way that this is done here prohibits nested interrupts!
+ * Otherwise, we will use the stack that was current when the interrupt was taken.
+ */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ ldr sp, =g_intstackbase
+ push r1 /* Save the MSP on the interrupt stack */
+ bl up_doirq /* R0=IRQ, R1=register save area on stack */
+ pop r1 /* Recover R1=main stack pointer */
+#else
+ msr msp, r1 /* We are using the main stack pointer */
+ bl up_doirq /* R0=IRQ, R1=register save area on stack */
+ mrs r1, msp /* Recover R1=main stack pointer */
+#endif
+
+ /* On return from up_doirq, R0 will hold a pointer to register context
+ * array to use for the interrupt return. If that return value is the same
+ * as current stack pointer, then things are relatively easy.
+ */
+
+ cmp r0, r1 /* Context switch? */
+ beq 1f /* Branch if no context switch */
+
+ /* We are returning with a pending context switch. This case is different
+ * because in this case, the register save structure does not lie on the
+ * stack but, rather within a TCB structure. We'll have to copy some
+ * values to the stack.
+ */
+
+ /* Copy the hardware-saved context to the stack, and restore the software
+ * saved context directly.
+ *
+ * XXX In the normal case, it appears that this entire operation is unnecessary;
+ * context switch time would be improved if we could work out when the stack
+ * is dirty and avoid the work...
+ */
+
+ add r1, r0, #SW_XCPT_SIZE /* R1=Address of HW save area in reg array */
+ ldmia r1!, {r4-r11} /* Fetch eight registers in HW save area */
+#ifdef CONFIG_ARCH_FPU
+ vldmia r1!, {s0-s15} /* Fetch sixteen FP registers in HW save area */
+ ldmia r1, {r2-r3} /* Fetch FPSCR and Reserved in HW save area */
+#endif
+ ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */
+#ifdef CONFIG_ARCH_FPU
+ stmdb r1!, {r2-r3} /* Store FPSCR and Reserved on the return stack */
+ vstmdb r1!, {s0-s15} /* Store sixteen FP registers on the return stack */
+#endif
+ stmdb r1!, {r4-r11} /* Store eight registers on the return stack */
+ ldmia r0!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */
+#ifdef CONFIG_ARCH_FPU
+ vldmia r0, {s16-s31} /* Recover S16-S31 */
+#endif
+
+ b 2f /* Re-join common logic */
+
+1:
+ /* We are returning with no context switch. We simply need to "unwind"
+ * the same stack frame that we created at entry.
+ */
+
+ ldmia r1!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */
+#ifdef CONFIG_ARCH_FPU
+ vldmia r1!, {s16-s31} /* Recover S16-S31 */
+#endif
+
+2:
+ /* The EXC_RETURN value tells us whether we are returning on the MSP or PSP
+ */
+
+ tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
+ ite eq /* next two instructions conditional */
+ msreq msp, r1 /* R1=The main stack pointer */
+ msrne psp, r1 /* R1=The process stack pointer */
+
+ /* Restore the interrupt state */
+
+ msr primask, r3 /* Restore interrupts */
+
+ /* Always return with R14 containing the special value that will: (1)
+ * return to thread mode, and (2) select the correct stack.
+ */
+
+ bx r14 /* And return */
+
+ .size exception_common, .-exception_common
+
+/************************************************************************************
+ * Name: up_interruptstack/g_intstackbase
+ *
+ * Description:
+ * Shouldn't happen
+ *
+ ************************************************************************************/
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ .bss
+ .global g_intstackbase
+ .align 4
+up_interruptstack:
+ .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3)
+g_intstackbase:
+ .size up_interruptstack, .-up_interruptstack
+#endif
+
+ .end
+
diff --git a/nuttx/arch/arm/src/armv7-m/up_fpu.S b/nuttx/arch/arm/src/armv7-m/up_fpu.S
new file mode 100644
index 000000000..707420f06
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_fpu.S
@@ -0,0 +1,286 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/stm32_fpu.S
+ *
+ * Copyright (C) 2011-2012 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.
+ *
+ ************************************************************************************/
+/*
+ * When this file is assembled, it will require the following GCC options:
+ *
+ * -mcpu=cortex-m3 -mfloat-abi=hard -mfpu=vfp -meabi=5
+ */
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <arch/irq.h>
+
+#ifdef CONFIG_ARCH_FPU
+
+/************************************************************************************
+ * Preprocessor Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Global Symbols
+ ************************************************************************************/
+
+ .globl up_savefpu
+ .globl up_restorefpu
+
+ .syntax unified
+ .thumb
+ .file "up_fpu.S"
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_savefpu
+ *
+ * Description:
+ * Given the pointer to a register save area (in R0), save the state of the
+ * floating point registers.
+ *
+ * C Function Prototype:
+ * void up_savefpu(uint32_t *regs);
+ *
+ * Input Parameters:
+ * regs - A pointer to the register save area in which to save the floating point
+ * registers
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+ .thumb_func
+ .type up_savefpu, function
+up_savefpu:
+
+ add r1, r0, #(4*REG_S0) /* R1=Address of FP register storage */
+
+ /* Some older GNU assemblers don't support all the newer UAL mnemonics. */
+
+#if 1 /* Use UAL mnemonics */
+ /* Store all floating point registers. Registers are stored in numeric order,
+ * s0, s1, ... in increasing address order.
+ */
+
+ vstmia r1!, {s0-s31} /* Save the full FP context */
+
+ /* Store the floating point control and status register. At the end of the
+ * vstmia, r1 will point to the FPCSR storage location.
+ */
+
+ vmrs r2, fpscr /* Fetch the FPCSR */
+ str r2, [r1], #4 /* Save the floating point control and status register */
+#else
+ /* Store all floating point registers */
+
+#if 1 /* Use store multiple */
+ fstmias r1!, {s0-s31} /* Save the full FP context */
+#else
+ vmov r2, r3, d0 /* r2, r3 = d0 */
+ str r2, [r1], #4 /* Save S0 and S1 values */
+ str r3, [r1], #4
+ vmov r2, r3, d1 /* r2, r3 = d1 */
+ str r2, [r1], #4 /* Save S2 and S3 values */
+ str r3, [r1], #4
+ vmov r2, r3, d2 /* r2, r3 = d2 */
+ str r2, [r1], #4 /* Save S4 and S5 values */
+ str r3, [r1], #4
+ vmov r2, r3, d3 /* r2, r3 = d3 */
+ str r2, [r1], #4 /* Save S6 and S7 values */
+ str r3, [r1], #4
+ vmov r2, r3, d4 /* r2, r3 = d4 */
+ str r2, [r1], #4 /* Save S8 and S9 values */
+ str r3, [r1], #4
+ vmov r2, r3, d5 /* r2, r3 = d5 */
+ str r2, [r1], #4 /* Save S10 and S11 values */
+ str r3, [r1], #4
+ vmov r2, r3, d6 /* r2, r3 = d6 */
+ str r2, [r1], #4 /* Save S12 and S13 values */
+ str r3, [r1], #4
+ vmov r2, r3, d7 /* r2, r3 = d7 */
+ str r2, [r1], #4 /* Save S14 and S15 values */
+ str r3, [r1], #4
+ vmov r2, r3, d8 /* r2, r3 = d8 */
+ str r2, [r1], #4 /* Save S16 and S17 values */
+ str r3, [r1], #4
+ vmov r2, r3, d9 /* r2, r3 = d9 */
+ str r2, [r1], #4 /* Save S18 and S19 values */
+ str r3, [r1], #4
+ vmov r2, r3, d10 /* r2, r3 = d10 */
+ str r2, [r1], #4 /* Save S20 and S21 values */
+ str r3, [r1], #4
+ vmov r2, r3, d11 /* r2, r3 = d11 */
+ str r2, [r1], #4 /* Save S22 and S23 values */
+ str r3, [r1], #4
+ vmov r2, r3, d12 /* r2, r3 = d12 */
+ str r2, [r1], #4 /* Save S24 and S25 values */
+ str r3, [r1], #4
+ vmov r2, r3, d13 /* r2, r3 = d13 */
+ str r2, [r1], #4 /* Save S26 and S27 values */
+ str r3, [r1], #4
+ vmov r2, r3, d14 /* r2, r3 = d14 */
+ str r2, [r1], #4 /* Save S28 and S29 values */
+ str r3, [r1], #4
+ vmov r2, r3, d15 /* r2, r3 = d15 */
+ str r2, [r1], #4 /* Save S30 and S31 values */
+ str r3, [r1], #4
+#endif
+
+ /* Store the floating point control and status register */
+
+ fmrx r2, fpscr /* Fetch the FPCSR */
+ str r2, [r1], #4 /* Save the floating point control and status register */
+#endif
+ bx lr
+
+ .size up_savefpu, .-up_savefpu
+
+/************************************************************************************
+ * Name: up_restorefpu
+ *
+ * Description:
+ * Given the pointer to a register save area (in R0), restore the state of the
+ * floating point registers.
+ *
+ * C Function Prototype:
+ * void up_restorefpu(const uint32_t *regs);
+ *
+ * Input Parameters:
+ * regs - A pointer to the register save area containing the floating point
+ * registers.
+ *
+ * Returned Value:
+ * This function does not return anything explicitly. However, it is called from
+ * interrupt level assembly logic that assumes that r0 is preserved.
+ *
+ ************************************************************************************/
+
+ .thumb_func
+ .type up_restorefpu, function
+up_restorefpu:
+
+ add r1, r0, #(4*REG_S0) /* R1=Address of FP register storage */
+
+ /* Some older GNU assemblers don't support all the newer UAL mnemonics. */
+
+#if 1 /* Use UAL mnemonics */
+ /* Load all floating point registers. Registers are loaded in numeric order,
+ * s0, s1, ... in increasing address order.
+ */
+
+ vldmia r1!, {s0-s31} /* Restore the full FP context */
+
+ /* Load the floating point control and status register. At the end of the
+ * vstmia, r1 will point to the FPCSR storage location.
+ */
+
+ ldr r2, [r1], #4 /* Fetch the floating point control and status register */
+ vmsr fpscr, r2 /* Restore the FPCSR */
+#else
+ /* Load all floating point registers Registers are loaded in numeric order,
+ * s0, s1, ... in increasing address order.
+ */
+
+#if 1 /* Use load multiple */
+ fldmias r1!, {s0-s31} /* Restore the full FP context */
+#else
+ ldr r2, [r1], #4 /* Fetch S0 and S1 values */
+ ldr r3, [r1], #4
+ vmov d0, r2, r3 /* Save as d0 */
+ ldr r2, [r1], #4 /* Fetch S2 and S3 values */
+ ldr r3, [r1], #4
+ vmov d1, r2, r3 /* Save as d1 */
+ ldr r2, [r1], #4 /* Fetch S4 and S5 values */
+ ldr r3, [r1], #4
+ vmov d2, r2, r3 /* Save as d2 */
+ ldr r2, [r1], #4 /* Fetch S6 and S7 values */
+ ldr r3, [r1], #4
+ vmov d3, r2, r3 /* Save as d3 */
+ ldr r2, [r1], #4 /* Fetch S8 and S9 values */
+ ldr r3, [r1], #4
+ vmov d4, r2, r3 /* Save as d4 */
+ ldr r2, [r1], #4 /* Fetch S10 and S11 values */
+ ldr r3, [r1], #4
+ vmov d5, r2, r3 /* Save as d5 */
+ ldr r2, [r1], #4 /* Fetch S12 and S13 values */
+ ldr r3, [r1], #4
+ vmov d6, r2, r3 /* Save as d6 */
+ ldr r2, [r1], #4 /* Fetch S14 and S15 values */
+ ldr r3, [r1], #4
+ vmov d7, r2, r3 /* Save as d7 */
+ ldr r2, [r1], #4 /* Fetch S16 and S17 values */
+ ldr r3, [r1], #4
+ vmov d8, r2, r3 /* Save as d8 */
+ ldr r2, [r1], #4 /* Fetch S18 and S19 values */
+ ldr r3, [r1], #4
+ vmov d9, r2, r3 /* Save as d9 */
+ ldr r2, [r1], #4 /* Fetch S20 and S21 values */
+ ldr r3, [r1], #4
+ vmov d10, r2, r3 /* Save as d10 */
+ ldr r2, [r1], #4 /* Fetch S22 and S23 values */
+ ldr r3, [r1], #4
+ vmov d11, r2, r3 /* Save as d11 */
+ ldr r2, [r1], #4 /* Fetch S24 and S25 values */
+ ldr r3, [r1], #4
+ vmov d12, r2, r3 /* Save as d12 */
+ ldr r2, [r1], #4 /* Fetch S26 and S27 values */
+ ldr r3, [r1], #4
+ vmov d13, r2, r3 /* Save as d13 */
+ ldr r2, [r1], #4 /* Fetch S28 and S29 values */
+ ldr r3, [r1], #4
+ vmov d14, r2, r3 /* Save as d14 */
+ ldr r2, [r1], #4 /* Fetch S30 and S31 values */
+ ldr r3, [r1], #4
+ vmov d15, r2, r3 /* Save as d15 */
+#endif
+
+ /* Load the floating point control and status register. r1 points t
+ * the address of the FPCSR register.
+ */
+
+ ldr r2, [r1], #4 /* Fetch the floating point control and status register */
+ fmxr fpscr, r2 /* Restore the FPCSR */
+#endif
+ bx lr
+
+ .size up_restorefpu, .-up_restorefpu
+#endif /* CONFIG_ARCH_FPU */
+ .end
+
diff --git a/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S b/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S
new file mode 100755
index 000000000..3ce51c9cd
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S
@@ -0,0 +1,95 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/up_fullcontextrestore.S
+ *
+ * Copyright (C) 2009, 2011 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 <arch/irq.h>
+
+#include "nvic.h"
+#include "svcall.h"
+
+/************************************************************************************
+ * Preprocessor Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Global Symbols
+ ************************************************************************************/
+
+ .syntax unified
+ .thumb
+ .file "up_fullcontextrestore.S"
+
+/************************************************************************************
+ * Macros
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_fullcontextrestore
+ *
+ * Description:
+ * Restore the current thread context. Full prototype is:
+ *
+ * void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn));
+ *
+ * Return:
+ * None
+ *
+ ************************************************************************************/
+
+ .thumb_func
+ .globl up_fullcontextrestore
+ .type up_fullcontextrestore, function
+up_fullcontextrestore:
+
+ /* Perform the System call with R0=1 and R1=regs */
+
+ mov r1, r0 /* R1: regs */
+ mov r0, #SYS_restore_context /* R0: restore context */
+ svc 0 /* Force synchronous SVCall (or Hard Fault) */
+
+ /* This call should not return */
+
+ bx lr /* Unnecessary ... will not return */
+ .size up_fullcontextrestore, .-up_fullcontextrestore
+ .end
+
diff --git a/nuttx/arch/arm/src/armv7-m/up_hardfault.c b/nuttx/arch/arm/src/armv7-m/up_hardfault.c
new file mode 100644
index 000000000..a9eea8103
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_hardfault.c
@@ -0,0 +1,144 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_hardfault.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <string.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include "up_arch.h"
+#include "os_internal.h"
+#include "nvic.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Debug output from this file may interfere with context switching! */
+
+#undef DEBUG_HARDFAULTS /* Define to debug hard faults */
+
+#ifdef DEBUG_HARDFAULTS
+# define hfdbg(format, arg...) lldbg(format, ##arg)
+#else
+# define hfdbg(x...)
+#endif
+
+#define INSN_SVC0 0xdf00 /* insn: svc 0 */
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_hardfault
+ *
+ * Description:
+ * This is Hard Fault exception handler. It also catches SVC call
+ * exceptions that are performed in bad contexts.
+ *
+ ****************************************************************************/
+
+int up_hardfault(int irq, FAR void *context)
+{
+ uint32_t *regs = (uint32_t*)context;
+ uint16_t *pc;
+ uint16_t insn;
+
+ /* Get the value of the program counter where the fault occurred */
+
+ pc = (uint16_t*)regs[REG_PC] - 1;
+ if ((void*)pc >= (void*)&_stext && (void*)pc < (void*)&_etext)
+ {
+ /* Fetch the instruction that caused the Hard fault */
+
+ insn = *pc;
+ hfdbg(" PC: %p INSN: %04x\n", pc, insn);
+
+ /* If this was the instruction 'svc 0', then forward processing
+ * to the SVCall handler
+ */
+
+ if (insn == INSN_SVC0)
+ {
+ hfdbg("Forward SVCall\n");
+ return up_svcall(irq, context);
+ }
+ }
+
+ /* Dump some hard fault info */
+
+ hfdbg("\nHard Fault:\n");
+ hfdbg(" IRQ: %d regs: %p\n", irq, regs);
+ hfdbg(" BASEPRI: %08x PRIMASK: %08x IPSR: %08x\n",
+ getbasepri(), getprimask(), getipsr());
+ hfdbg(" CFAULTS: %08x HFAULTS: %08x DFAULTS: %08x BFAULTADDR: %08x AFAULTS: %08x\n",
+ getreg32(NVIC_CFAULTS), getreg32(NVIC_HFAULTS),
+ getreg32(NVIC_DFAULTS), getreg32(NVIC_BFAULT_ADDR),
+ getreg32(NVIC_AFAULTS));
+ hfdbg(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
+ regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
+ hfdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
+ regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
+ hfdbg(" PSR=%08x\n", regs[REG_XPSR]);
+
+ (void)irqsave();
+ lldbg("PANIC!!! Hard fault: %08x\n", getreg32(NVIC_HFAULTS));
+ PANIC(OSERR_UNEXPECTEDISR);
+ return OK;
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_initialstate.c b/nuttx/arch/arm/src/armv7-m/up_initialstate.c
new file mode 100644
index 000000000..52a2682a0
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_initialstate.c
@@ -0,0 +1,200 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_initialstate.c
+ *
+ * Copyright (C) 2009, 2011-2 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 <string.h>
+
+#include <nuttx/arch.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "psr.h"
+#include "exc_return.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_initial_state
+ *
+ * Description:
+ * A new thread is being started and a new TCB
+ * has been created. This function is called to initialize
+ * the processor specific portions of the new TCB.
+ *
+ * This function must setup the intial architecture registers
+ * and/or stack so that execution will begin at tcb->start
+ * on the next context switch.
+ *
+ ****************************************************************************/
+
+void up_initial_state(_TCB *tcb)
+{
+ struct xcptcontext *xcp = &tcb->xcp;
+
+ /* Initialize the initial exception register context structure */
+
+ memset(xcp, 0, sizeof(struct xcptcontext));
+
+ /* Save the initial stack pointer */
+
+ xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr;
+
+ /* Set the stack limit value */
+
+ xcp->regs[REG_R10] = (uint32_t)tcb->stack_alloc_ptr + 64;
+
+ /* Fill the stack with a watermark value */
+
+ memset(tcb->stack_alloc_ptr, 0xff, tcb->adj_stack_size);
+
+ /* Save the task entry point (stripping off the thumb bit) */
+
+ xcp->regs[REG_PC] = (uint32_t)tcb->start & ~1;
+
+ /* Specify thumb mode */
+
+ xcp->regs[REG_XPSR] = ARMV7M_XPSR_T;
+
+ /* If this task is running PIC, then set the PIC base register to the
+ * address of the allocated D-Space region.
+ */
+
+#ifdef CONFIG_PIC
+ if (tcb->dspace != NULL)
+ {
+ /* Set the PIC base register (probably R10) to the address of the
+ * alloacated D-Space region.
+ */
+
+ xcp->regs[REG_PIC] = (uint32_t)tcb->dspace->region;
+ }
+
+ /* Make certain that bit 0 is set in the main entry address. This
+ * is only an issue when NXFLAT is enabled. NXFLAT doesn't know
+ * anything about thumb; the addresses that NXFLAT sets are based
+ * on file header info and won't have bit 0 set.
+ */
+
+#ifdef CONFIG_NXFLAT
+ tcb->entry.main = (main_t)((uint32_t)tcb->entry.main | 1);
+#endif
+#endif /* CONFIG_PIC */
+
+#ifdef CONFIG_ARMV7M_CMNVECTOR
+ /* Set privileged- or unprivileged-mode, depending on how NuttX is
+ * configured and what kind of thread is being started.
+ *
+ * If the kernel build is not selected, then all threads run in
+ * privileged thread mode.
+ *
+ * If FPU support is not configured, set the bit that indicates that
+ * the context does not include the volatile FP registers.
+ */
+
+ xcp->regs[REG_EXC_RETURN] = EXC_RETURN_BASE | EXC_RETURN_THREAD_MODE;
+
+#ifndef CONFIG_ARCH_FPU
+
+ xcp->regs[REG_EXC_RETURN] |= EXC_RETURN_STD_CONTEXT;
+
+#else
+
+ xcp->regs[REG_FPSCR] = 0; // XXX initial FPSCR should be configurable
+ xcp->regs[REG_FPReserved] = 0;
+
+#endif
+
+#ifdef CONFIG_NUTTX_KERNEL
+ if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL)
+ {
+ /* It is a normal task or a pthread. Set user mode */
+
+ xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PROCESS_STACK;
+ }
+#endif
+
+#else /* CONFIG_ARMV7M_CMNVECTOR */
+
+ /* Set privileged- or unprivileged-mode, depending on how NuttX is
+ * configured and what kind of thread is being started.
+ *
+ * If the kernel build is not selected, then all threads run in
+ * privileged thread mode.
+ */
+
+#ifdef CONFIG_NUTTX_KERNEL
+ if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL)
+ {
+ /* It is a kernel thread.. set privileged thread mode */
+
+ xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
+ }
+ else
+ {
+ /* It is a normal task or a pthread. Set user mode */
+
+ xcp->regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
+ }
+#endif
+#endif /* CONFIG_ARMV7M_CMNVECTOR */
+
+ /* Enable or disable interrupts, based on user configuration */
+
+#ifdef CONFIG_SUPPRESS_INTERRUPTS
+ xcp->regs[REG_PRIMASK] = 1;
+#endif
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_memfault.c b/nuttx/arch/arm/src/armv7-m/up_memfault.c
new file mode 100644
index 000000000..bbe3f6573
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_memfault.c
@@ -0,0 +1,110 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_memfault.c
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include "up_arch.h"
+#include "os_internal.h"
+#include "nvic.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#undef DEBUG_MEMFAULTS /* Define to debug memory management faults */
+
+#ifdef DEBUG_MEMFAULTS
+# define mfdbg(format, arg...) lldbg(format, ##arg)
+#else
+# define mfdbg(x...)
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_memfault
+ *
+ * Description:
+ * This is Memory Management Fault exception handler. Normally we get here
+ * when the Cortex M3 MPU is enabled and an MPU fault is detected. However,
+ * I understand that there are other error conditions that can also generate
+ * memory management faults.
+ *
+ ****************************************************************************/
+
+int up_memfault(int irq, FAR void *context)
+{
+ /* Dump some memory management fault info */
+
+ (void)irqsave();
+ lldbg("PANIC!!! Memory Management Fault:\n");
+ mfdbg(" IRQ: %d context: %p\n", irq, regs);
+ lldbg(" CFAULTS: %08x MMFAR: %08x\n",
+ getreg32(NVIC_CFAULTS), getreg32(NVIC_MEMMANAGE_ADDR));
+ mfdbg(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
+ regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
+ mfdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
+ regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
+ mfdbg(" PSR=%08x\n", regs[REG_XPSR]);
+
+ PANIC(OSERR_UNEXPECTEDISR);
+ return OK;
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_mpu.c b/nuttx/arch/arm/src/armv7-m/up_mpu.c
new file mode 100644
index 000000000..27936562c
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_mpu.c
@@ -0,0 +1,176 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_mpu.c
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 "mpu.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This set represents the set of disabled memory sub-regions. A bit set
+ * corresponds to a disabled sub-region; the LS bit corresponds to the first
+ * region. The array is indexed by the number of subregions: 0 means no sub-
+ * regions (0xff), and 0 means all subregions but one (0x00).
+ */
+
+static const void uint8_t g_regionmap[9] =
+{
+ 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00
+};
+
+/* The next available region number */
+
+static uint8_t g_region;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mpu_allocregion
+ *
+ * Description:
+ * Allocate the next region
+ *
+ * Assumptions:
+ * - Regions are never deallocated
+ * - Regions are only allocated early in initialization, so nothing
+ * special is require;
+ *
+ ****************************************************************************/
+
+unsigned int mpu_allocregion(void)
+{
+ return (unsigned int)g_region++;
+}
+
+/****************************************************************************
+ * Name: mpu_log2regionsize
+ *
+ * Description:
+ * Determine the smallest value of l2size (log base 2 size) such that the
+ * following is true:
+ *
+ * size <= (1 << l2size)
+ *
+ ****************************************************************************/
+
+uint8_t mpu_log2regionsize(size_t size)
+{
+ /* The minimum permitted region size is 16 bytes (log2(16) = 4. */
+
+ uint32_t l2size;
+ for (l2size = 4; l2size < 32 && size > (1 << l2size); size++);
+ return l2size;
+}
+
+/****************************************************************************
+ * Name: mpu_subregion
+ *
+ * Description:
+ * Given the size of the (1) memory to be mapped and (2) the log2 size
+ * of the mapping to use, determine the minimal sub-region set to span
+ * that memory region.
+ *
+ * Assumption:
+ * l2size has the same properties as the return value from
+ * mpu_log2regionsize()
+ *
+ ****************************************************************************/
+
+uint32_t mpu_subregion(size_t size, uint8_t l2size)
+{
+ unsigned int nsrs
+ uint32_t asize;
+ uint32_t mask;
+
+ /* Eight subregions are support. The representation is as an 8-bit
+ * value with the LS bit corresponding to subregion 0. A bit is set
+ * to disable the sub-region.
+ *
+ * l2size: Log2 of the actual region size is <= (1 << l2size);
+ */
+
+ DEBUGASSERT(lsize > 3 && size <= (1 << l2size));
+
+ /* Examples with l2size = 12:
+ *
+ * Shifted Adjusted Number Sub-Region
+ * Size Mask Size Shift Sub-Regions Bitset
+ * 0x1000 0x01ff 0x1000 9 8 0x00
+ * 0x0c00 0x01ff 0x0c00 9 6 0x03
+ * 0x0c40 0x01ff 0x0e00 9 7 0x01
+ */
+
+ if (l2size < 32)
+ {
+ mask = ((1 << lsize)-1) >> 3; /* Shifted mask */
+ }
+
+ /* The 4Gb region size is a special case */
+
+ else
+ {
+ /* NOTE: There is no way to represent a 4Gb region size in the 32-bit
+ * input.
+ */
+
+ mask = 0x1fffffff; /* Shifted mask */
+ }
+
+ asize = (size + mask) & ~mask; /* Adjusted size */
+ nsrs = asize >> (lsize-3); /* Number of subregions */
+ return g_regionmap[nsrs];
+}
+
+
+
diff --git a/nuttx/arch/arm/src/armv7-m/up_releasepending.c b/nuttx/arch/arm/src/armv7-m/up_releasepending.c
new file mode 100755
index 000000000..2f0d4dc39
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_releasepending.c
@@ -0,0 +1,129 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_releasepending.c
+ *
+ * Copyright (C) 2007-2009, 2012 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 <sched.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_release_pending
+ *
+ * Description:
+ * Release and ready-to-run tasks that have
+ * collected in the pending task list. This can call a
+ * context switch if a new task is placed at the head of
+ * the ready to run list.
+ *
+ ****************************************************************************/
+
+void up_release_pending(void)
+{
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+
+ slldbg("From TCB=%p\n", rtcb);
+
+ /* Merge the g_pendingtasks list into the g_readytorun task list */
+
+ /* sched_lock(); */
+ if (sched_mergepending())
+ {
+ /* The currently active task has changed! We will need to switch
+ * contexts. First check if we are operating in interrupt context.
+ */
+
+ if (current_regs)
+ {
+ /* Yes, then we have to do things differently. Just copy the
+ * current_regs into the OLD rtcb.
+ */
+
+ up_savestate(rtcb->xcp.regs);
+
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+ slldbg("New Active Task TCB=%p\n", rtcb);
+
+ /* Then switch contexts */
+
+ up_restorestate(rtcb->xcp.regs);
+ }
+
+ /* No, then we will need to perform the user context switch */
+
+ else
+ {
+ /* Switch context to the context of the task at the head of the
+ * ready to run list.
+ */
+
+ _TCB *nexttcb = (_TCB*)g_readytorun.head;
+ up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+
+ /* up_switchcontext forces a context switch to the task at the
+ * head of the ready-to-run list. It does not 'return' in the
+ * normal sense. When it does return, it is because the blocked
+ * task is again ready to run and has execution priority.
+ */
+ }
+ }
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c b/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c
new file mode 100755
index 000000000..f1c961b15
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c
@@ -0,0 +1,182 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_reprioritizertr.c
+ *
+ * Copyright (C) 2007-2009, 2012 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 <stdbool.h>
+#include <sched.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_reprioritize_rtr
+ *
+ * Description:
+ * Called when the priority of a running or
+ * ready-to-run task changes and the reprioritization will
+ * cause a context switch. Two cases:
+ *
+ * 1) The priority of the currently running task drops and the next
+ * task in the ready to run list has priority.
+ * 2) An idle, ready to run task's priority has been raised above the
+ * the priority of the current, running task and it now has the
+ * priority.
+ *
+ * Inputs:
+ * tcb: The TCB of the task that has been reprioritized
+ * priority: The new task priority
+ *
+ ****************************************************************************/
+
+void up_reprioritize_rtr(_TCB *tcb, uint8_t priority)
+{
+ /* Verify that the caller is sane */
+
+ if (tcb->task_state < FIRST_READY_TO_RUN_STATE ||
+ tcb->task_state > LAST_READY_TO_RUN_STATE ||
+ priority < SCHED_PRIORITY_MIN ||
+ priority > SCHED_PRIORITY_MAX)
+ {
+ PANIC(OSERR_BADREPRIORITIZESTATE);
+ }
+ else
+ {
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+ bool switch_needed;
+
+ slldbg("TCB=%p PRI=%d\n", tcb, priority);
+
+ /* Remove the tcb task from the ready-to-run list.
+ * sched_removereadytorun will return true if we just removed the head
+ * of the ready to run list.
+ */
+
+ switch_needed = sched_removereadytorun(tcb);
+
+ /* Setup up the new task priority */
+
+ tcb->sched_priority = (uint8_t)priority;
+
+ /* Return the task to the ready-to-run task list. sched_addreadytorun
+ * will return true if the task was added to the head of ready-to-run
+ * list. We will need to perform a context switch only if the
+ * EXCLUSIVE or of the two calls is non-zero (i.e., one and only one
+ * the calls changes the head of the ready-to-run list).
+ */
+
+ switch_needed ^= sched_addreadytorun(tcb);
+
+ /* Now, perform the context switch if one is needed (i.e. if the head
+ * of the ready-to-run list is no longer the same).
+ */
+
+ if (switch_needed)
+ {
+ /* If we are going to do a context switch, then now is the right
+ * time to add any pending tasks back into the ready-to-run list.
+ * task list now
+ */
+
+ if (g_pendingtasks.head)
+ {
+ sched_mergepending();
+ }
+
+ /* Are we in an interrupt handler? */
+
+ if (current_regs)
+ {
+ /* Yes, then we have to do things differently.
+ * Just copy the current_regs into the OLD rtcb.
+ */
+
+ up_savestate(rtcb->xcp.regs);
+
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+ slldbg("New Active Task TCB=%p\n", rtcb);
+
+ /* Then switch contexts */
+
+ up_restorestate(rtcb->xcp.regs);
+ }
+
+ /* No, then we will need to perform the user context switch */
+
+ else
+ {
+ /* Switch context to the context of the task at the head of the
+ * ready to run list.
+ */
+
+ _TCB *nexttcb = (_TCB*)g_readytorun.head;
+ up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+
+ /* up_switchcontext forces a context switch to the task at the
+ * head of the ready-to-run list. It does not 'return' in the
+ * normal sense. When it does return, it is because the blocked
+ * task is again ready to run and has execution priority.
+ */
+ }
+ }
+ }
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_saveusercontext.S b/nuttx/arch/arm/src/armv7-m/up_saveusercontext.S
new file mode 100755
index 000000000..c8da07430
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_saveusercontext.S
@@ -0,0 +1,104 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/up_saveusercontext.S
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <arch/irq.h>
+
+#include "nvic.h"
+#include "svcall.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Global Symbols
+ ************************************************************************************/
+
+ .syntax unified
+ .thumb
+ .file "up_saveusercontext.S"
+
+/************************************************************************************
+ * Macros
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_saveusercontext
+ *
+ * Description:
+ * Save the current thread context. Full prototype is:
+ *
+ * int up_saveusercontext(uint32_t *saveregs);
+ *
+ * Return:
+ * 0: Normal return
+ * 1: Context switch return
+ *
+ ************************************************************************************/
+
+ .text
+ .thumb_func
+ .globl up_saveusercontext
+ .type up_saveusercontext, function
+up_saveusercontext:
+
+ /* Perform the System call with R0=0 and R1=regs */
+
+ mov r1, r0 /* R1: regs */
+ mov r0, #SYS_save_context /* R0: save context (also return value) */
+ svc 0 /* Force synchronous SVCall (or Hard Fault) */
+
+ /* There are two return conditions. On the first return, R0 (the
+ * return value will be zero. On the second return we need to
+ * force R0 to be 1.
+ */
+
+ add r2, r1, #(4*REG_R0)
+ mov r3, #1
+ str r3, [r2, #0]
+ bx lr /* "normal" return with r0=0 or
+ * context switch with r0=1 */
+ .size up_saveusercontext, .-up_saveusercontext
+ .end
+
diff --git a/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c b/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c
new file mode 100644
index 000000000..9e6dbd14b
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_schedulesigaction.c
@@ -0,0 +1,208 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_schedulesigaction.c
+ *
+ * Copyright (C) 2009-2012 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 <sched.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+
+#include "psr.h"
+#include "os_internal.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+#ifndef CONFIG_DISABLE_SIGNALS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_schedule_sigaction
+ *
+ * Description:
+ * This function is called by the OS when one or more
+ * signal handling actions have been queued for execution.
+ * The architecture specific code must configure things so
+ * that the 'igdeliver' callback is executed on the thread
+ * specified by 'tcb' as soon as possible.
+ *
+ * This function may be called from interrupt handling logic.
+ *
+ * This operation should not cause the task to be unblocked
+ * nor should it cause any immediate execution of sigdeliver.
+ * Typically, a few cases need to be considered:
+ *
+ * (1) This function may be called from an interrupt handler
+ * During interrupt processing, all xcptcontext structures
+ * should be valid for all tasks. That structure should
+ * be modified to invoke sigdeliver() either on return
+ * from (this) interrupt or on some subsequent context
+ * switch to the recipient task.
+ * (2) If not in an interrupt handler and the tcb is NOT
+ * the currently executing task, then again just modify
+ * the saved xcptcontext structure for the recipient
+ * task so it will invoke sigdeliver when that task is
+ * later resumed.
+ * (3) If not in an interrupt handler and the tcb IS the
+ * currently executing task -- just call the signal
+ * handler now.
+ *
+ ****************************************************************************/
+
+void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver)
+{
+ /* Refuse to handle nested signal actions */
+
+ sdbg("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver);
+
+ if (!tcb->xcp.sigdeliver)
+ {
+ irqstate_t flags;
+
+ /* Make sure that interrupts are disabled */
+
+ flags = irqsave();
+
+ /* First, handle some special cases when the signal is
+ * being delivered to the currently executing task.
+ */
+
+ sdbg("rtcb=0x%p current_regs=0x%p\n", g_readytorun.head, current_regs);
+
+ if (tcb == (_TCB*)g_readytorun.head)
+ {
+ /* CASE 1: We are not in an interrupt handler and
+ * a task is signalling itself for some reason.
+ */
+
+ if (!current_regs)
+ {
+ /* In this case just deliver the signal now. */
+
+ sigdeliver(tcb);
+ }
+
+ /* CASE 2: We are in an interrupt handler AND the
+ * interrupted task is the same as the one that
+ * must receive the signal, then we will have to modify
+ * the return state as well as the state in the TCB.
+ *
+ * Hmmm... there looks like a latent bug here: The following
+ * logic would fail in the strange case where we are in an
+ * interrupt handler, the thread is signalling itself, but
+ * a context switch to another task has occurred so that
+ * current_regs does not refer to the thread at g_readytorun.head!
+ */
+
+ else
+ {
+ /* Save the return lr and cpsr and one scratch register
+ * These will be restored by the signal trampoline after
+ * the signals have been delivered.
+ */
+
+ tcb->xcp.sigdeliver = sigdeliver;
+ tcb->xcp.saved_pc = current_regs[REG_PC];
+ tcb->xcp.saved_primask = current_regs[REG_PRIMASK];
+ tcb->xcp.saved_xpsr = current_regs[REG_XPSR];
+
+ /* Then set up to vector to the trampoline with interrupts
+ * disabled
+ */
+
+ current_regs[REG_PC] = (uint32_t)up_sigdeliver;
+ current_regs[REG_PRIMASK] = 1;
+ current_regs[REG_XPSR] = ARMV7M_XPSR_T;
+
+ /* And make sure that the saved context in the TCB
+ * is the same as the interrupt return context.
+ */
+
+ up_savestate(tcb->xcp.regs);
+ }
+ }
+
+ /* Otherwise, we are (1) signaling a task is not running
+ * from an interrupt handler or (2) we are not in an
+ * interrupt handler and the running task is signalling
+ * some non-running task.
+ */
+
+ else
+ {
+ /* Save the return lr and cpsr and one scratch register
+ * These will be restored by the signal trampoline after
+ * the signals have been delivered.
+ */
+
+ tcb->xcp.sigdeliver = sigdeliver;
+ tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
+ tcb->xcp.saved_primask = tcb->xcp.regs[REG_PRIMASK];
+ tcb->xcp.saved_xpsr = tcb->xcp.regs[REG_XPSR];
+
+ /* Then set up to vector to the trampoline with interrupts
+ * disabled
+ */
+
+ tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
+ tcb->xcp.regs[REG_PRIMASK] = 1;
+ tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T;
+ }
+
+ irqrestore(flags);
+ }
+}
+
+#endif /* !CONFIG_DISABLE_SIGNALS */
diff --git a/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c b/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c
new file mode 100644
index 000000000..3c340b8d3
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_sigdeliver.c
@@ -0,0 +1,142 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_sigdeliver.c
+ *
+ * Copyright (C) 2009-2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sched.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+#ifndef CONFIG_DISABLE_SIGNALS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_sigdeliver
+ *
+ * Description:
+ * This is the a signal handling trampoline. When a signal action was
+ * posted. The task context was mucked with and forced to branch to this
+ * location with interrupts disabled.
+ *
+ ****************************************************************************/
+
+void up_sigdeliver(void)
+{
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+ uint32_t regs[XCPTCONTEXT_REGS];
+ sig_deliver_t sigdeliver;
+
+ /* Save the errno. This must be preserved throughout the signal handling
+ * so that the user code final gets the correct errno value (probably
+ * EINTR).
+ */
+
+ int saved_errno = rtcb->pterrno;
+
+ up_ledon(LED_SIGNAL);
+
+ sdbg("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
+ rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
+ ASSERT(rtcb->xcp.sigdeliver != NULL);
+
+ /* Save the real return state on the stack. */
+
+ up_copystate(regs, rtcb->xcp.regs);
+ regs[REG_PC] = rtcb->xcp.saved_pc;
+ regs[REG_PRIMASK] = rtcb->xcp.saved_primask;
+ regs[REG_XPSR] = rtcb->xcp.saved_xpsr;
+
+ /* Get a local copy of the sigdeliver function pointer. We do this so that
+ * we can nullify the sigdeliver function pointer in the TCB and accept
+ * more signal deliveries while processing the current pending signals.
+ */
+
+ sigdeliver = rtcb->xcp.sigdeliver;
+ rtcb->xcp.sigdeliver = NULL;
+
+ /* Then restore the task interrupt state */
+
+ irqrestore((uint16_t)regs[REG_PRIMASK]);
+
+ /* Deliver the signals */
+
+ sigdeliver(rtcb);
+
+ /* Output any debug messages BEFORE restoring errno (because they may
+ * alter errno), then disable interrupts again and restore the original
+ * errno that is needed by the user logic (it is probably EINTR).
+ */
+
+ sdbg("Resuming\n");
+ (void)irqsave();
+ rtcb->pterrno = saved_errno;
+
+ /* Then restore the correct state for this thread of
+ * execution.
+ */
+
+ up_ledoff(LED_SIGNAL);
+ up_fullcontextrestore(regs);
+}
+
+#endif /* !CONFIG_DISABLE_SIGNALS */
+
diff --git a/nuttx/arch/arm/src/armv7-m/up_stackcheck.c b/nuttx/arch/arm/src/armv7-m/up_stackcheck.c
new file mode 100644
index 000000000..e8f02a863
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_stackcheck.c
@@ -0,0 +1,40 @@
+
+
+void __cyg_profile_func_enter(void *func, void *caller) __attribute__((naked, no_instrument_function));
+void __cyg_profile_func_exit(void *func, void *caller) __attribute__((naked, no_instrument_function));
+void __stack_overflow_trap(void) __attribute__((naked, no_instrument_function));
+
+void
+__stack_overflow_trap(void)
+{
+ /* if we get here, the stack has overflowed */
+ asm ( "b .");
+}
+
+void
+__cyg_profile_func_enter(void *func, void *caller)
+{
+ asm volatile (
+ " mrs r2, ipsr \n" /* Check whether we are in interrupt mode */
+ " cmp r2, #0 \n" /* since we don't switch r10 on interrupt entry, we */
+ " bne 2f \n" /* can't detect overflow of the interrupt stack. */
+ " \n"
+ " sub r2, sp, #68 \n" /* compute stack pointer as though we just stacked a full frame */
+ " mrs r1, control \n" /* Test CONTROL.FPCA to see whether we also need room for the FP */
+ " tst r1, #4 \n" /* context. */
+ " beq 1f \n"
+ " sub r2, r2, #136 \n" /* subtract FP context frame size */
+ "1: \n"
+ " cmp r2, r10 \n" /* compare stack with limit */
+ " bgt 2f \n" /* stack is above limit and thus OK */
+ " b __stack_overflow_trap\n"
+ "2: \n"
+ " bx lr \n"
+ );
+}
+
+void
+__cyg_profile_func_exit(void *func, void *caller)
+{
+ asm volatile("bx lr");
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_svcall.c b/nuttx/arch/arm/src/armv7-m/up_svcall.c
new file mode 100644
index 000000000..5a4d64fe2
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_svcall.c
@@ -0,0 +1,363 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_svcall.c
+ *
+ * Copyright (C) 2009, 2011-2012 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 <string.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+#include <nuttx/sched.h>
+
+#ifdef CONFIG_NUTTX_KERNEL
+# include <syscall.h>
+#endif
+
+#include "svcall.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+
+#undef SYSCALL_INTERRUPTIBLE
+#if defined(CONFIG_NUTTX_KERNEL)
+# if CONFIG_ARCH_INTERRUPTSTACK > 3
+# warning "CONFIG_ARCH_INTERRUPTSTACK and CONFIG_NUTTX_KERNEL are incompatible"
+# warning "options as currently implemented. Interrupts will have to be disabled"
+# warning "during SYScall processing to avoid un-handled nested interrupts"
+# else
+# define SYSCALL_INTERRUPTIBLE 1
+# endif
+#endif
+
+/* Debug ********************************************************************/
+/* Debug output from this file may interfere with context switching! To get
+ * debug output you must enabled the following in your NuttX configuration:
+ *
+ * CONFIG_DEBUG and CONFIG_DEBUG_SCHED
+ *
+ * And you must explicitly define DEBUG_SVCALL below:
+ */
+
+#undef DEBUG_SVCALL /* Define to debug SVCall */
+#ifdef DEBUG_SVCALL
+# define svcdbg(format, arg...) slldbg(format, ##arg)
+#else
+# define svcdbg(x...)
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: dispatch_syscall
+ *
+ * Description:
+ * Dispatch a system call to the appropriate handling logic.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NUTTX_KERNEL
+static inline void dispatch_syscall(uint32_t *regs)
+{
+ uint32_t cmd = regs[REG_R0];
+ FAR _TCB *rtcb = sched_self();
+ uintptr_t ret = (uintptr_t)ERROR;
+
+ /* Verify the the SYS call number is within range */
+
+ if (cmd < SYS_maxsyscall)
+ {
+ /* Report error and return ERROR */
+
+ slldbg("ERROR: Bad SYS call: %d\n", cmd);
+ }
+ else
+ {
+ /* The index into the syscall table is offset by the number of architecture-
+ * specific reserved entries at the beginning of the SYS call number space.
+ */
+
+ int index = cmd - CONFIG_SYS_RESERVED;
+
+ /* Enable interrupts while the SYSCALL executes */
+
+#ifdef SYSCALL_INTERRUPTIBLE
+ irqenable();
+#endif
+
+ /* Call the correct stub for each SYS call, based on the number of parameters */
+
+ svcdbg("Calling stub%d at %p\n", index, g_stubloopkup[index].stub0);
+
+ switch (g_stubnparms[index])
+ {
+ /* No parameters */
+
+ case 0:
+ ret = g_stublookup[index].stub0();
+ break;
+
+ /* Number of parameters: 1 */
+
+ case 1:
+ ret = g_stublookup[index].stub1(regs[REG_R1]);
+ break;
+
+ /* Number of parameters: 2 */
+
+ case 2:
+ ret = g_stublookup[index].stub2(regs[REG_R1], regs[REG_R2]);
+ break;
+
+ /* Number of parameters: 3 */
+
+ case 3:
+ ret = g_stublookup[index].stub3(regs[REG_R1], regs[REG_R2],
+ regs[REG_R3]);
+ break;
+
+ /* Number of parameters: 4 */
+
+ case 4:
+ ret = g_stublookup[index].stub4(regs[REG_R1], regs[REG_R2],
+ regs[REG_R3], regs[REG_R4]);
+ break;
+
+ /* Number of parameters: 5 */
+
+ case 5:
+ ret = g_stublookup[index].stub5(regs[REG_R1], regs[REG_R2],
+ regs[REG_R3], regs[REG_R4],
+ regs[REG_R5]);
+ break;
+
+ /* Number of parameters: 6 */
+
+ case 6:
+ ret = g_stublookup[index].stub6(regs[REG_R1], regs[REG_R2],
+ regs[REG_R3], regs[REG_R4],
+ regs[REG_R5], regs[REG_R6]);
+ break;
+
+ /* Unsupported number of paramters. Report error and return ERROR */
+
+ default:
+ slldbg("ERROR: Bad SYS call %d number parameters %d\n",
+ cmd, g_stubnparms[index]);
+ break;
+ }
+
+#ifdef SYSCALL_INTERRUPTIBLE
+ irqdisable();
+#endif
+ }
+
+ /* Set up the return value. First, check if a context switch occurred.
+ * In this case, regs will no longer be the same as current_regs. In
+ * the case of a context switch, we will have to save the return value
+ * in the TCB where it can be returned later when the task is restarted.
+ */
+
+ if (regs != current_regs)
+ {
+ regs = rtcb->xcp.regs;
+ }
+
+ /* Then return the result in R0 */
+
+ svcdbg("Return value regs: %p value: %d\n", regs, ret);
+ regs[REG_R0] = (uint32_t)ret;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_svcall
+ *
+ * Description:
+ * This is SVCall exception handler that performs context switching
+ *
+ ****************************************************************************/
+
+int up_svcall(int irq, FAR void *context)
+{
+ uint32_t *regs = (uint32_t*)context;
+
+ DEBUGASSERT(regs && regs == current_regs);
+
+ /* The SVCall software interrupt is called with R0 = system call command
+ * and R1..R7 = variable number of arguments depending on the system call.
+ */
+
+ svcdbg("SVCALL Entry: regs: %p cmd: %d\n", regs, regs[REG_R0]);
+ svcdbg(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
+ regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
+ svcdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
+ regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
+ svcdbg(" PSR=%08x\n", regs[REG_XPSR]);
+
+ /* Handle the SVCall according to the command in R0 */
+
+ switch (regs[REG_R0])
+ {
+ /* R0=SYS_save_context: This is a save context command:
+ *
+ * int up_saveusercontext(uint32_t *saveregs);
+ *
+ * At this point, the following values are saved in context:
+ *
+ * R0 = SYS_save_context
+ * R1 = saveregs
+ *
+ * In this case, we simply need to copy the current regsters to the
+ * save register space references in the saved R1 and return.
+ */
+
+ case SYS_save_context:
+ {
+ DEBUGASSERT(regs[REG_R1] != 0);
+ memcpy((uint32_t*)regs[REG_R1], regs, XCPTCONTEXT_SIZE);
+#if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_ARMV7M_CMNVECTOR)
+ up_savefpu((uint32_t*)regs[REG_R1]);
+#endif
+ }
+ break;
+
+ /* R0=SYS_restore_context: This a restore context command:
+ *
+ * void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn));
+ *
+ * At this point, the following values are saved in context:
+ *
+ * R0 = SYS_restore_context
+ * R1 = restoreregs
+ *
+ * In this case, we simply need to set current_regs to restore register
+ * area referenced in the saved R1. context == current_regs is the normal
+ * exception return. By setting current_regs = context[R1], we force
+ * the return to the saved context referenced in R1.
+ */
+
+ case SYS_restore_context:
+ {
+ DEBUGASSERT(regs[REG_R1] != 0);
+ current_regs = (uint32_t*)regs[REG_R1];
+ }
+ break;
+
+ /* R0=SYS_switch_context: This a switch context command:
+ *
+ * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
+ *
+ * At this point, the following values are saved in context:
+ *
+ * R0 = 1
+ * R1 = saveregs
+ * R2 = restoreregs
+ *
+ * In this case, we do both: We save the context registers to the save
+ * register area reference by the saved contents of R1 and then set
+ * current_regs to to the save register area referenced by the saved
+ * contents of R2.
+ */
+
+ case SYS_switch_context:
+ {
+ DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
+ memcpy((uint32_t*)regs[REG_R1], regs, XCPTCONTEXT_SIZE);
+#if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_ARMV7M_CMNVECTOR)
+ up_savefpu((uint32_t*)regs[REG_R1]);
+#endif
+ current_regs = (uint32_t*)regs[REG_R2];
+ }
+ break;
+
+ /* This is not an architecture-specific system call. If NuttX is built
+ * as a standalone kernel with a system call interface, then all of the
+ * additional system calls must be handled as in the default case.
+ */
+
+ default:
+#ifdef CONFIG_NUTTX_KERNEL
+ dispatch_syscall(regs);
+#else
+ slldbg("ERROR: Bad SYS call: %d\n", regs[REG_R0]);
+#endif
+ break;
+ }
+
+ /* Report what happened. That might difficult in the case of a context switch */
+
+ if (regs != current_regs)
+ {
+ svcdbg("SVCall Return: Context switch!\n");
+ svcdbg(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ current_regs[REG_R0], current_regs[REG_R1], current_regs[REG_R2], current_regs[REG_R3],
+ current_regs[REG_R4], current_regs[REG_R5], current_regs[REG_R6], current_regs[REG_R7]);
+ svcdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ current_regs[REG_R8], current_regs[REG_R9], current_regs[REG_R10], current_regs[REG_R11],
+ current_regs[REG_R12], current_regs[REG_R13], current_regs[REG_R14], current_regs[REG_R15]);
+ svcdbg(" PSR=%08x\n", current_regs[REG_XPSR]);
+ }
+ else
+ {
+ svcdbg("SVCall Return: %d\n", regs[REG_R0]);
+ }
+
+ return OK;
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_switchcontext.S b/nuttx/arch/arm/src/armv7-m/up_switchcontext.S
new file mode 100755
index 000000000..854f6fa16
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_switchcontext.S
@@ -0,0 +1,97 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/up_switchcontext.S
+ *
+ * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <arch/irq.h>
+
+#include "nvic.h"
+#include "svcall.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Global Symbols
+ ************************************************************************************/
+
+ .syntax unified
+ .thumb
+ .file "up_switchcontext.S"
+
+/************************************************************************************
+ * Macros
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_switchcontext
+ *
+ * Description:
+ * Save the current thread context and restore the specified context.
+ * Full prototype is:
+ *
+ * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
+ *
+ * Return:
+ * None
+ *
+ ************************************************************************************/
+
+ .thumb_func
+ .globl up_switchcontext
+ .type up_switchcontext, function
+up_switchcontext:
+
+ /* Perform the System call with R0=1, R1=saveregs, R2=restoreregs */
+
+ mov r2, r1 /* R2: restoreregs */
+ mov r1, r0 /* R1: saveregs */
+ mov r0, #SYS_switch_context /* R0: context switch */
+ svc 0 /* Force synchronous SVCall (or Hard Fault) */
+
+ /* This call should not return */
+
+ bx lr /* Unnecessary ... will not return */
+ .size up_switchcontext, .-up_switchcontext
+ .end
+
diff --git a/nuttx/arch/arm/src/armv7-m/up_unblocktask.c b/nuttx/arch/arm/src/armv7-m/up_unblocktask.c
new file mode 100755
index 000000000..da10f0376
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_unblocktask.c
@@ -0,0 +1,157 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_unblocktask.c
+ *
+ * Copyright (C) 2007-2009, 2012 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 <sched.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "clock_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_unblock_task
+ *
+ * Description:
+ * A task is currently in an inactive task list
+ * but has been prepped to execute. Move the TCB to the
+ * ready-to-run list, restore its context, and start execution.
+ *
+ * Inputs:
+ * tcb: Refers to the tcb to be unblocked. This tcb is
+ * in one of the waiting tasks lists. It must be moved to
+ * the ready-to-run list and, if it is the highest priority
+ * ready to run taks, executed.
+ *
+ ****************************************************************************/
+
+void up_unblock_task(_TCB *tcb)
+{
+ /* Verify that the context switch can be performed */
+
+ if ((tcb->task_state < FIRST_BLOCKED_STATE) ||
+ (tcb->task_state > LAST_BLOCKED_STATE))
+ {
+ PANIC(OSERR_BADUNBLOCKSTATE);
+ }
+ else
+ {
+ _TCB *rtcb = (_TCB*)g_readytorun.head;
+
+ /* Remove the task from the blocked task list */
+
+ sched_removeblocked(tcb);
+
+ /* Reset its timeslice. This is only meaningful for round
+ * robin tasks but it doesn't here to do it for everything
+ */
+
+#if CONFIG_RR_INTERVAL > 0
+ tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK;
+#endif
+
+ /* Add the task in the correct location in the prioritized
+ * g_readytorun task list
+ */
+
+ if (sched_addreadytorun(tcb))
+ {
+ /* The currently active task has changed! We need to do
+ * a context switch to the new task.
+ *
+ * Are we in an interrupt handler?
+ */
+
+ if (current_regs)
+ {
+ /* Yes, then we have to do things differently.
+ * Just copy the current_regs into the OLD rtcb.
+ */
+
+ up_savestate(rtcb->xcp.regs);
+
+ /* Restore the exception context of the rtcb at the (new) head
+ * of the g_readytorun task list.
+ */
+
+ rtcb = (_TCB*)g_readytorun.head;
+
+ /* Then switch contexts */
+
+ up_restorestate(rtcb->xcp.regs);
+ }
+
+ /* No, then we will need to perform the user context switch */
+
+ else
+ {
+ /* Switch context to the context of the task at the head of the
+ * ready to run list.
+ */
+
+ _TCB *nexttcb = (_TCB*)g_readytorun.head;
+ up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+
+ /* up_switchcontext forces a context switch to the task at the
+ * head of the ready-to-run list. It does not 'return' in the
+ * normal sense. When it does return, it is because the blocked
+ * task is again ready to run and has execution priority.
+ */
+ }
+ }
+ }
+}
diff --git a/nuttx/arch/arm/src/armv7-m/up_vectors.c b/nuttx/arch/arm/src/armv7-m/up_vectors.c
new file mode 100644
index 000000000..b85ac9246
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_vectors.c
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * arch/arm/src/armv7-m/up_vectors.c
+ *
+ * Copyright (C) 2012 Michael Smith. All rights reserved.
+ *
+ * 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 "chip.h"
+
+/************************************************************************************
+ * Preprocessor Definitions
+ ************************************************************************************/
+
+#define IDLE_STACK ((unsigned)&_ebss+CONFIG_IDLETHREAD_STACKSIZE-4)
+
+#ifndef ARMV7M_PERIPHERAL_INTERRUPTS
+# error ARMV7M_PERIPHERAL_INTERRUPTS must be defined to the number of I/O interrupts to be supported
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* Chip-specific entrypoint */
+
+extern void __start(void);
+
+/* Common exception entrypoint */
+
+extern void exception_common(void);
+
+/************************************************************************************
+ * Public data
+ ************************************************************************************/
+
+/* Provided by the linker script to indicate the end of the BSS */
+
+extern char _ebss;
+
+/* The v7m vector table consists of an array of function pointers, with the first
+ * slot (vector zero) used to hold the initial stack pointer.
+ *
+ * As all exceptions (interrupts) are routed via exception_common, we just need to
+ * fill this array with pointers to it.
+ *
+ * Note that the [ ... ] desginated initialiser is a GCC extension.
+ */
+
+unsigned _vectors[] __attribute__((section(".vectors"))) =
+ {
+ /* Initial stack */
+
+ IDLE_STACK,
+
+ /* Reset exception handler */
+
+ (unsigned)&__start,
+
+ /* Vectors 2 - n point directly at the generic handler */
+
+ [2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = (unsigned)&exception_common
+ };
diff --git a/nuttx/arch/arm/src/common/up_allocateheap.c b/nuttx/arch/arm/src/common/up_allocateheap.c
new file mode 100644
index 000000000..fbd1421a7
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_allocateheap.c
@@ -0,0 +1,83 @@
+/****************************************************************************
+ * arch/arm/src/common/up_allocateheap.c
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Private Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocate_heap
+ *
+ * Description:
+ * The heap may be statically allocated by
+ * defining CONFIG_HEAP_BASE and CONFIG_HEAP_SIZE. If these
+ * are not defined, then this function will be called to
+ * dynamically set aside the heap region.
+ *
+ ****************************************************************************/
+
+void up_allocate_heap(FAR void **heap_start, size_t *heap_size)
+{
+ up_ledon(LED_HEAPALLOCATE);
+ *heap_start = (FAR void*)g_heapbase;
+ *heap_size = CONFIG_DRAM_END - g_heapbase;
+}
diff --git a/nuttx/arch/arm/src/common/up_arch.h b/nuttx/arch/arm/src/common/up_arch.h
new file mode 100644
index 000000000..b612f6af2
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_arch.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+ * arch/arm/src/common/up_arch.h
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_COMMON_UP_ARCH_H
+#define ___ARCH_ARM_SRC_COMMON_UP_ARCH_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#ifndef __ASSEMBLY__
+# include <stdint.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+# define getreg8(a) (*(volatile uint8_t *)(a))
+# define putreg8(v,a) (*(volatile uint8_t *)(a) = (v))
+# define getreg32(a) (*(volatile uint32_t *)(a))
+# define putreg32(v,a) (*(volatile uint32_t *)(a) = (v))
+
+/* Some compiler options will convert short loads and stores into byte loads
+ * and stores. We don't want this to happen for IO reads and writes!
+ */
+
+/* # define getreg16(a) (*(volatile uint16_t *)(a)) */
+static inline uint16_t getreg16(unsigned int addr)
+{
+ uint16_t retval;
+ __asm__ __volatile__("\tldrh %0, [%1]\n\t" : "=r"(retval) : "r"(addr));
+ return retval;
+}
+
+/* define putreg16(v,a) (*(volatile uint16_t *)(a) = (v)) */
+static inline void putreg16(uint16_t val, unsigned int addr)
+{
+ __asm__ __volatile__("\tstrh %0, [%1]\n\t": : "r"(val), "r"(addr));
+}
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/* Atomic modification of registers */
+
+EXTERN void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits);
+EXTERN void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits);
+EXTERN void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* ___ARCH_ARM_SRC_COMMON_UP_ARCH_H */
diff --git a/nuttx/arch/arm/src/common/up_checkstack.c b/nuttx/arch/arm/src/common/up_checkstack.c
new file mode 100644
index 000000000..6c13f63d1
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_checkstack.c
@@ -0,0 +1,147 @@
+/****************************************************************************
+ * arch/arm/src/common/up_checkstack.c
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+
+#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_check_stack
+ *
+ * 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 _TCB *tcb)
+{
+ FAR uint32_t *ptr;
+ size_t mark;
+
+ /* The ARM uses 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 *)tcb->stack_alloc_ptr, mark = tcb->adj_stack_size/4;
+ *ptr == 0xDEADBEEF && 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 > tcb->adj_stack_size/4)
+ {
+ int i, j;
+
+ ptr = (FAR uint32_t *)tcb->stack_alloc_ptr;
+ for (i = 0; i < tcb->adj_stack_size; i += 4*64)
+ {
+ for (j = 0; j < 64; j++)
+ {
+ int ch;
+ if (*ptr++ == 0xDEADBEEF)
+ {
+ ch = '.';
+ }
+ else
+ {
+ ch = 'X';
+ }
+ up_putc(ch);
+ }
+ up_putc('\n');
+ }
+ }
+#endif
+
+ /* Return our guess about how much stack space was used */
+
+ return mark*4;
+}
+
+size_t up_check_stack(void)
+{
+ return up_check_tcbstack((FAR _TCB*)g_readytorun.head);
+}
+
+size_t up_check_stack_remain(void)
+{
+ return ((FAR _TCB*)g_readytorun.head)->adj_stack_size - up_check_tcbstack((FAR _TCB*)g_readytorun.head);
+}
+
+#endif /* CONFIG_DEBUG && CONFIG_DEBUG_STACK */
diff --git a/nuttx/arch/arm/src/common/up_createstack.c b/nuttx/arch/arm/src/common/up_createstack.c
new file mode 100644
index 000000000..3d6dfef45
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_createstack.c
@@ -0,0 +1,197 @@
+/****************************************************************************
+ * arch/arm/src/common/up_createstack.c
+ *
+ * Copyright (C) 2007-2012 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 <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Macros
+ ****************************************************************************/
+
+/* ARM requires at least a 4-byte stack alignment. For use with EABI and
+ * floating point, the stack must be aligned to 8-byte addresses.
+ */
+
+#ifndef CONFIG_STACK_ALIGNMENT
+
+/* The symbol __ARM_EABI__ is defined by GCC if EABI is being used. If you
+ * are not using GCC, make sure that CONFIG_STACK_ALIGNMENT is set correctly!
+ */
+
+# ifdef __ARM_EABI__
+# define CONFIG_STACK_ALIGNMENT 8
+# else
+# define CONFIG_STACK_ALIGNMENT 4
+# endif
+#endif
+
+/* Stack alignment macros */
+
+#define STACK_ALIGN_MASK (CONFIG_STACK_ALIGNMENT-1)
+#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK)
+#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: memset32
+ *
+ * On most larger then 8 bit archs this will need to be word aligned so
+ * so maybe some checks should be put in place?
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
+static void *memset32(void *s, uint32_t c, size_t n)
+{
+ uint32_t *p = (uint32_t *)s;
+ while (n-- > 0) *p++ = c;
+ return s;
+}
+#endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_create_stack
+ *
+ * Description:
+ * Allocate a stack for a new thread and setup
+ * up stack-related information in the TCB.
+ *
+ * The following TCB fields must be initialized:
+ * adj_stack_size: Stack size after adjustment for hardware,
+ * processor, etc. This value is retained only for debug
+ * purposes.
+ * stack_alloc_ptr: Pointer to allocated stack
+ * adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The
+ * initial value of the stack pointer.
+ *
+ * Inputs:
+ * tcb: The TCB of new task
+ * stack_size: The requested stack size. At least this much
+ * must be allocated.
+ ****************************************************************************/
+
+int up_create_stack(_TCB *tcb, size_t stack_size)
+{
+ if (tcb->stack_alloc_ptr &&
+ tcb->adj_stack_size != stack_size)
+ {
+ sched_free(tcb->stack_alloc_ptr);
+ tcb->stack_alloc_ptr = NULL;
+ }
+
+ if (!tcb->stack_alloc_ptr)
+ {
+#ifdef CONFIG_DEBUG
+ tcb->stack_alloc_ptr = (uint32_t*)kzalloc(stack_size);
+#else
+ tcb->stack_alloc_ptr = (uint32_t*)kmalloc(stack_size);
+#endif
+ }
+
+ if (tcb->stack_alloc_ptr)
+ {
+ size_t top_of_stack;
+ size_t size_of_stack;
+
+ /* The ARM uses a push-down stack: the stack grows toward lower
+ * addresses in memory. The stack pointer register, points to
+ * the lowest, valid work address (the "top" of the stack). Items
+ * on the stack are referenced as positive word offsets from sp.
+ */
+
+ top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4;
+
+ /* The ARM stack must be aligned; 4 byte alignment for OABI and
+ * 8-byte alignment for EABI. If necessary top_of_stack must be
+ * rounded down to the next boundary
+ */
+
+ top_of_stack = STACK_ALIGN_DOWN(top_of_stack);
+
+ /* The size of the stack in bytes is then the difference between
+ * the top and the bottom of the stack (+4 because if the top
+ * is the same as the bottom, then the size is one 32-bit element).
+ * The size need not be aligned.
+ */
+
+ size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
+
+ /* Save the adjusted stack values in the _TCB */
+
+ tcb->adj_stack_ptr = (uint32_t*)top_of_stack;
+ tcb->adj_stack_size = size_of_stack;
+
+ /* If stack debug is enabled, then fill the stack with a
+ * recognizable value that we can use later to test for high
+ * water marks.
+ */
+
+#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
+ memset32(tcb->stack_alloc_ptr, 0xDEADBEEF, tcb->adj_stack_size/4);
+#endif
+
+ up_ledon(LED_STACKCREATED);
+ return OK;
+ }
+
+ return ERROR;
+}
+
diff --git a/nuttx/arch/arm/src/common/up_etherstub.c b/nuttx/arch/arm/src/common/up_etherstub.c
new file mode 100755
index 000000000..1c4a71ce6
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_etherstub.c
@@ -0,0 +1,86 @@
+/****************************************************************************
+ * arch/arm/src/common/up_etherstub.c
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 "up_internal.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_netinitialize (stub)
+ *
+ * Description:
+ * This is a stub version os up_netinitialize. Normally, up_netinitialize
+ * is defined in board/up_network.c for board-specific ethernet
+ * implementations, or chip/xyx_ethernet.c for chip-specific ethernet
+ * implementations. The stub version here is used in the cornercase where
+ * the network is enable yet there is no ethernet driver to be initialized.
+ * In this case, up_initialize will still try to call up_netinitialize()
+ * when one does not exist. This cornercase would occur if, for example,
+ * only a USB network interface is being used or perhaps if a SLIP is
+ * being used).
+ *
+ * In the long run, it might be better to have some kind of CONFIG_NO_ETHERNET
+ * to suppress the call to up_netinitialize() in up_initialize(). Then
+ * this stub would not be needed.
+ *
+ ****************************************************************************/
+
+void up_netinitialize(void)
+{
+}
diff --git a/nuttx/arch/arm/src/common/up_exit.c b/nuttx/arch/arm/src/common/up_exit.c
new file mode 100644
index 000000000..6f6d54f76
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_exit.c
@@ -0,0 +1,174 @@
+/****************************************************************************
+ * common/up_exit.c
+ *
+ * Copyright (C) 2007-2009, 2012 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 <sched.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+#ifdef CONFIG_DUMP_ON_EXIT
+#include <nuttx/fs/fs.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: _up_dumponexit
+ *
+ * Description:
+ * Dump the state of all tasks whenever on task exits. This is debug
+ * instrumentation that was added to check file-related reference counting
+ * but could be useful again sometime in the future.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG)
+static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
+{
+#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NFILE_STREAMS > 0
+ int i;
+#endif
+
+ sdbg(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
+ sdbg(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+ if (tcb->filelist)
+ {
+ sdbg(" filelist refcount=%d\n",
+ tcb->filelist->fl_crefs);
+
+ for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
+ {
+ struct inode *inode = tcb->filelist->fl_files[i].f_inode;
+ if (inode)
+ {
+ sdbg(" fd=%d refcount=%d\n",
+ i, inode->i_crefs);
+ }
+ }
+ }
+#endif
+
+#if CONFIG_NFILE_STREAMS > 0
+ if (tcb->streams)
+ {
+ sdbg(" streamlist refcount=%d\n",
+ tcb->streams->sl_crefs);
+
+ for (i = 0; i < CONFIG_NFILE_STREAMS; i++)
+ {
+ struct file_struct *filep = &tcb->streams->sl_streams[i];
+ if (filep->fs_filedes >= 0)
+ {
+#if CONFIG_STDIO_BUFFER_SIZE > 0
+ sdbg(" fd=%d nbytes=%d\n",
+ filep->fs_filedes,
+ filep->fs_bufpos - filep->fs_bufstart);
+#else
+ sdbg(" fd=%d\n", filep->fs_filedes);
+#endif
+ }
+ }
+ }
+#endif
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: _exit
+ *
+ * Description:
+ * This function causes the currently executing task to cease
+ * to exist. This is a special case of task_delete() where the task to
+ * be deleted is the currently executing task. It is more complex because
+ * a context switch must be perform to the next ready to run task.
+ *
+ ****************************************************************************/
+
+void _exit(int status)
+{
+ _TCB* tcb;
+
+ /* Disable interrupts. They will be restored when the next
+ * task is started.
+ */
+
+ (void)irqsave();
+
+ slldbg("TCB=%p exitting\n", g_readytorun.head);
+
+#if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG)
+ slldbg("Other tasks:\n");
+ sched_foreach(_up_dumponexit, NULL);
+#endif
+
+ /* Destroy the task at the head of the ready to run list. */
+
+ (void)task_deletecurrent();
+
+ /* Now, perform the context switch to the new ready-to-run task at the
+ * head of the list.
+ */
+
+ tcb = (_TCB*)g_readytorun.head;
+
+ /* Then switch contexts */
+
+ up_fullcontextrestore(tcb->xcp.regs);
+}
+
diff --git a/nuttx/arch/arm/src/common/up_idle.c b/nuttx/arch/arm/src/common/up_idle.c
new file mode 100644
index 000000000..62557c3a8
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_idle.c
@@ -0,0 +1,91 @@
+/****************************************************************************
+ * arch/arm/src/common/up_idle.c
+ *
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <nuttx/arch.h>
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_idle
+ *
+ * Description:
+ * up_idle() is the logic that will be executed when their is no other
+ * ready-to-run task. This is processor idle time and will continue until
+ * some interrupt occurs to cause a context switch from the idle task.
+ *
+ * Processing in this state may be processor-specific. e.g., this is where
+ * power management operations might be performed.
+ *
+ ****************************************************************************/
+
+void up_idle(void)
+{
+#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS)
+ /* If the system is idle and there are no timer interrupts, then process
+ * "fake" timer interrupts. Hopefully, something will wake up.
+ */
+
+ sched_process_timer();
+#else
+
+ /* Sleep until an interrupt occurs to save power */
+
+#if 0
+ asm("WFI"); /* For example */
+#endif
+#endif
+}
+
diff --git a/nuttx/arch/arm/src/common/up_initialize.c b/nuttx/arch/arm/src/common/up_initialize.c
new file mode 100644
index 000000000..094835c29
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_initialize.c
@@ -0,0 +1,191 @@
+/****************************************************************************
+ * arch/arm/src/common/up_initialize.c
+ *
+ * Copyright (C) 2007-2010, 2012 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 <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/ramlog.h>
+
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_calibratedelay
+ *
+ * Description:
+ * Delay loops are provided for short timing loops. This function, if
+ * enabled, will just wait for 100 seconds. Using a stopwatch, you can
+ * can then determine if the timing loops are properly calibrated.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_ARCH_CALIBRATION) && defined(CONFIG_DEBUG)
+static void up_calibratedelay(void)
+{
+ int i;
+ lldbg("Beginning 100s delay\n");
+ for (i = 0; i < 100; i++)
+ {
+ up_mdelay(1000);
+ }
+ lldbg("End 100s delay\n");
+}
+#else
+# define up_calibratedelay()
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_initialize
+ *
+ * Description:
+ * up_initialize will be called once during OS initialization after the
+ * basic OS services have been initialized. The architecture specific
+ * details of initializing the OS will be handled here. Such things as
+ * setting up interrupt service routines, starting the clock, and
+ * registering device drivers are some of the things that are different
+ * for each processor and hardware platform.
+ *
+ * up_initialize is called after the OS initialized but before the user
+ * initialization logic has been started and before the libraries have
+ * been initialized. OS services and driver services are available.
+ *
+ ****************************************************************************/
+
+void up_initialize(void)
+{
+ /* Initialize global variables */
+
+ current_regs = NULL;
+
+ /* Calibrate the timing loop */
+
+ up_calibratedelay();
+
+ /* Add any extra memory fragments to the memory manager */
+
+ up_addregion();
+
+ /* Initialize the interrupt subsystem */
+
+ up_irqinitialize();
+
+ /* Initialize the power management subsystem. This MCU-specific function
+ * must be called *very* early in the intialization sequence *before* any
+ * other device drivers are initialized (since they may attempt to register
+ * with the power management subsystem).
+ */
+
+#ifdef CONFIG_PM
+ up_pminitialize();
+#endif
+
+ /* Initialize the DMA subsystem if the weak function stm32_dmainitialize has been
+ * brought into the build
+ */
+
+#ifdef CONFIG_ARCH_DMA
+#ifdef CONFIG_HAVE_WEAKFUNCTIONS
+ if (up_dmainitialize)
+#endif
+ {
+ up_dmainitialize();
+ }
+#endif
+
+ /* Initialize the system timer interrupt */
+
+#if !defined(CONFIG_SUPPRESS_INTERRUPTS) && !defined(CONFIG_SUPPRESS_TIMER_INTS)
+ up_timerinit();
+#endif
+
+ /* Register devices */
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+ devnull_register(); /* Standard /dev/null */
+#endif
+
+ /* Initialize the console device driver */
+
+#if defined(USE_SERIALDRIVER)
+ up_serialinit();
+#elif defined(CONFIG_DEV_LOWCONSOLE)
+ lowconsole_init();
+#elif defined(CONFIG_RAMLOG_CONSOLE)
+ ramlog_consoleinit();
+#endif
+
+ /* Initialize the system logging device */
+
+#ifdef CONFIG_SYSLOG_CHAR
+ syslog_initialize();
+#endif
+#ifdef CONFIG_RAMLOG_SYSLOG
+ ramlog_sysloginit();
+#endif
+
+ /* Initialize the network */
+
+ up_netinitialize();
+
+ /* Initialize USB -- device and/or host */
+
+ up_usbinitialize();
+ up_ledon(LED_IRQSENABLED);
+}
diff --git a/nuttx/arch/arm/src/common/up_internal.h b/nuttx/arch/arm/src/common/up_internal.h
new file mode 100644
index 000000000..45cb1dcc0
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_internal.h
@@ -0,0 +1,393 @@
+/****************************************************************************
+ * common/up_internal.h
+ *
+ * Copyright (C) 2007-2012 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_COMMON_UP_INTERNAL_H
+#define __ARCH_ARM_SRC_COMMON_UP_INTERNAL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+# include <sys/types.h>
+# include <stdint.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Bring-up debug configurations. These are here (vs defconfig)
+ * because these should only be controlled during low level
+ * board bring-up and not part of normal platform configuration.
+ */
+
+#undef CONFIG_SUPPRESS_INTERRUPTS /* DEFINED: Do not enable interrupts */
+#undef CONFIG_SUPPRESS_TIMER_INTS /* DEFINED: No timer */
+#undef CONFIG_SUPPRESS_SERIAL_INTS /* DEFINED: Console will poll */
+#undef CONFIG_SUPPRESS_UART_CONFIG /* DEFINED: Do not reconfig UART */
+#undef CONFIG_DUMP_ON_EXIT /* DEFINED: Dump task state on exit */
+
+/* Determine which (if any) console driver to use */
+
+#if !defined(CONFIG_DEV_CONSOLE) || CONFIG_NFILE_DESCRIPTORS == 0
+# undef USE_SERIALDRIVER
+# undef USE_EARLYSERIALINIT
+# undef CONFIG_DEV_LOWCONSOLE
+# undef CONFIG_RAMLOG_CONSOLE
+#else
+# if defined(CONFIG_RAMLOG_CONSOLE)
+# undef USE_SERIALDRIVER
+# undef USE_EARLYSERIALINIT
+# undef CONFIG_DEV_LOWCONSOLE
+# elif defined(CONFIG_DEV_LOWCONSOLE)
+# undef USE_SERIALDRIVER
+# undef USE_EARLYSERIALINIT
+# else
+# define USE_SERIALDRIVER 1
+# define USE_EARLYSERIALINIT 1
+# endif
+#endif
+
+/* Determine which device to use as the system logging device */
+
+#ifndef CONFIG_SYSLOG
+# undef CONFIG_SYSLOG_CHAR
+# undef CONFIG_RAMLOG_SYSLOG
+#endif
+
+/* Check if an interrupt stack size is configured */
+
+#ifndef CONFIG_ARCH_INTERRUPTSTACK
+# define CONFIG_ARCH_INTERRUPTSTACK 0
+#endif
+
+/* Macros to handle saving and restoring interrupt state. In the current ARM
+ * model, the state is always copied to and from the stack and TCB. In the
+ * Cortex-M3 model, the state is copied from the stack to the TCB, but only
+ * a referenced is passed to get the state from the TCB.
+ */
+
+#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4)
+# if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_ARMV7M_CMNVECTOR)
+# define up_savestate(regs) \
+ do { \
+ up_copystate(regs, (uint32_t*)current_regs); \
+ up_savefpu(regs); \
+ } \
+ while (0)
+# else
+# define up_savestate(regs) up_copystate(regs, (uint32_t*)current_regs)
+# endif
+# define up_restorestate(regs) (current_regs = regs)
+#else
+# define up_savestate(regs) up_copystate(regs, (uint32_t*)current_regs)
+# define up_restorestate(regs) up_copystate((uint32_t*)current_regs, regs)
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+typedef void (*up_vector_t)(void);
+#endif
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+/* This holds a references to the current interrupt level
+ * register storage structure. If is non-NULL only during
+ * interrupt processing.
+ */
+
+extern volatile uint32_t *current_regs;
+
+/* This is the beginning of heap as provided from up_head.S.
+ * This is the first address in DRAM after the loaded
+ * program+bss+idle stack. The end of the heap is
+ * CONFIG_DRAM_END
+ */
+
+extern const uint32_t g_heapbase;
+
+/* Address of the saved user stack pointer */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4)
+extern uint32_t g_intstackbase;
+# else
+extern uint32_t g_userstack;
+# endif
+#endif
+
+/* 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:
+ *
+ * - The linker script defines, for example, the symbol_sdata.
+ * - The declareion extern uint32_t _sdata; makes C happy. C will believe
+ * that the value _sdata is the address of a uint32_t variable _data (it is
+ * not!).
+ * - We can recoved the linker value then by simply taking the address of
+ * of _data. like: uint32_t *pdata = &_sdata;
+ */
+
+extern uint32_t _stext; /* Start of .text */
+extern uint32_t _etext; /* End_1 of .text + .rodata */
+extern const uint32_t _eronly; /* End+1 of read only section (.text + .rodata) */
+extern uint32_t _sdata; /* Start of .data */
+extern uint32_t _edata; /* End+1 of .data */
+extern uint32_t _sbss; /* Start of .bss */
+extern uint32_t _ebss; /* End+1 of .bss */
+
+/* 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,
+ *
+ * int __ramfunc__ foo (void);
+ * int __ramfunc__ foo (void) { return bar; }
+ *
+ * will create a function named foo that will execute from RAM.
+ */
+
+#ifdef CONFIG_BOOT_RAMFUNCS
+
+# define __ramfunc__ __attribute__ ((section(".ramfunc")))
+
+/* Functions decleared in the .ramfunc section will be packaged together
+ * by the linker script and stored in FLASH. During boot-up, the start
+ * logic must include logic to copy the RAM functions from their storage
+ * location in FLASH to their correct destination in SRAM. The following
+ * following linker-defined values provide the information to copy the
+ * functions from flash to RAM.
+ */
+
+extern const uint32_t _framfuncs; /* Copy source address in FLASH */
+extern uint32_t _sramfuncs; /* Copy destination start address in RAM */
+extern uint32_t _eramfuncs; /* Copy destination start address in RAM */
+
+#endif /* CONFIG_BOOT_RAMFUNCS */
+#endif /* __ASSEMBLY__ */
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/* Low level initialization provided by board-level logic ******************/
+
+extern void up_boot(void);
+
+/* Context switching */
+
+extern void up_copystate(uint32_t *dest, uint32_t *src);
+extern void up_decodeirq(uint32_t *regs);
+extern int up_saveusercontext(uint32_t *saveregs);
+extern void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn));
+extern void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
+
+/* Signal handling **********************************************************/
+
+extern void up_sigdeliver(void);
+
+/* Power management *********************************************************/
+
+#ifdef CONFIG_PM
+extern void up_pminitialize(void);
+#else
+# define up_pminitialize()
+#endif
+
+/* Interrupt handling *******************************************************/
+
+extern void up_irqinitialize(void);
+extern void up_maskack_irq(int irq);
+
+#if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4)
+
+extern uint32_t *up_doirq(int irq, uint32_t *regs);
+extern int up_svcall(int irq, FAR void *context);
+extern int up_hardfault(int irq, FAR void *context);
+extern int up_memfault(int irq, FAR void *context);
+
+#else /* CONFIG_ARCH_CORTEXM3 || CONFIG_ARCH_CORTEXM4 */
+
+extern void up_doirq(int irq, uint32_t *regs);
+#ifdef CONFIG_PAGING
+extern void up_pginitialize(void);
+extern uint32_t *up_va2pte(uintptr_t vaddr);
+extern void up_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr);
+#else /* CONFIG_PAGING */
+# define up_pginitialize()
+extern void up_dataabort(uint32_t *regs);
+#endif /* CONFIG_PAGING */
+extern void up_prefetchabort(uint32_t *regs);
+extern void up_syscall(uint32_t *regs);
+extern void up_undefinedinsn(uint32_t *regs);
+
+#endif /* CONFIG_ARCH_CORTEXM3 || CONFIG_ARCH_CORTEXM4 */
+
+extern void up_vectorundefinsn(void);
+extern void up_vectorswi(void);
+extern void up_vectorprefetch(void);
+extern void up_vectordata(void);
+extern void up_vectoraddrexcptn(void);
+extern void up_vectorirq(void);
+extern void up_vectorfiq(void);
+
+/* Floating point unit ******************************************************/
+
+#ifdef CONFIG_ARCH_FPU
+extern void up_savefpu(uint32_t *regs);
+extern void up_restorefpu(const uint32_t *regs);
+#else
+# define up_savefpu(regs)
+# define up_restorefpu(regs)
+#endif
+
+/* System timer *************************************************************/
+
+extern void up_timerinit(void);
+extern int up_timerisr(int irq, uint32_t *regs);
+
+/* Low level serial output **************************************************/
+
+extern void up_lowputc(char ch);
+extern void up_puts(const char *str);
+extern void up_lowputs(const char *str);
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+extern void up_earlyserialinit(void);
+extern void up_serialinit(void);
+#else
+# define up_earlyserialinit()
+# define up_serialinit()
+#endif
+
+/* Defined in drivers/lowconsole.c */
+
+#ifdef CONFIG_DEV_LOWCONSOLE
+extern void lowconsole_init(void);
+#else
+# define lowconsole_init()
+#endif
+
+/* DMA **********************************************************************/
+
+#ifdef CONFIG_ARCH_DMA
+extern void weak_function up_dmainitialize(void);
+#endif
+
+/* Memory management ********************************************************/
+
+#if CONFIG_MM_REGIONS > 1
+void up_addregion(void);
+#else
+# define up_addregion()
+#endif
+
+/* Watchdog timer ***********************************************************/
+
+extern void up_wdtinit(void);
+
+/* LED interfaces provided by board-level logic *****************************/
+
+#ifdef CONFIG_ARCH_LEDS
+extern void up_ledinit(void);
+extern void up_ledon(int led);
+extern void up_ledoff(int led);
+#else
+# define up_ledinit()
+# define up_ledon(led)
+# define up_ledoff(led)
+#endif
+
+/* Networking ***************************************************************/
+
+/* Defined in board/up_network.c for board-specific ethernet implementations,
+ * or chip/xyx_ethernet.c for chip-specific ethernet implementations, or
+ * common/up_etherstub.c for a cornercase where the network is enabled yet
+ * there is no ethernet driver to be initialized.
+ */
+
+#ifdef CONFIG_NET
+extern void up_netinitialize(void);
+#else
+# define up_netinitialize()
+#endif
+
+/* USB **********************************************************************/
+
+#ifdef CONFIG_USBDEV
+extern void up_usbinitialize(void);
+extern void up_usbuninitialize(void);
+#else
+# define up_usbinitialize()
+# define up_usbuninitialize()
+#endif
+
+/****************************************************************************
+ * Name: up_check_stack
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
+extern size_t up_check_stack(void);
+extern size_t up_check_tcbstack(FAR _TCB);
+extern size_t up_check_tcbstack_remain(FAR _TCB);
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM_SRC_COMMON_UP_INTERNAL_H */
diff --git a/nuttx/arch/arm/src/common/up_interruptcontext.c b/nuttx/arch/arm/src/common/up_interruptcontext.c
new file mode 100644
index 000000000..b67ad523a
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_interruptcontext.c
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * arch/arm/src/common/up_interruptcontext.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <stdbool.h>
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+
+#include "up_internal.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_interrupt_context
+ *
+ * Description: Return true is we are currently executing in
+ * the interrupt handler context.
+ ****************************************************************************/
+
+bool up_interrupt_context(void)
+{
+ return current_regs != NULL;
+}
diff --git a/nuttx/arch/arm/src/common/up_lowputs.c b/nuttx/arch/arm/src/common/up_lowputs.c
new file mode 100644
index 000000000..8b2919a05
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_lowputs.c
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * arch/arm/src/common/up_lowputs.c
+ *
+ * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_lowputs
+ *
+ * Description:
+ * This is a low-level helper function used to support debug.
+ *
+ ****************************************************************************/
+
+void up_lowputs(const char *str)
+{
+ while(*str)
+ {
+ up_lowputc(*str++);
+ }
+}
diff --git a/nuttx/arch/arm/src/common/up_mdelay.c b/nuttx/arch/arm/src/common/up_mdelay.c
new file mode 100644
index 000000000..b9b9ffc0e
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_mdelay.c
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * arch/arm/src/common/up_mdelay.c
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <nuttx/arch.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_mdelay
+ *
+ * Description:
+ * Delay inline for the requested number of milliseconds.
+ * *** NOT multi-tasking friendly ***
+ *
+ * ASSUMPTIONS:
+ * The setting CONFIG_BOARD_LOOPSPERMSEC has been calibrated
+ *
+ ****************************************************************************/
+
+void up_mdelay(unsigned int milliseconds)
+{
+ volatile int i;
+ volatile int j;
+
+ for (i = 0; i < milliseconds; i++)
+ {
+ for (j = 0; j < CONFIG_BOARD_LOOPSPERMSEC; j++)
+ {
+ }
+ }
+}
diff --git a/nuttx/arch/arm/src/common/up_modifyreg16.c b/nuttx/arch/arm/src/common/up_modifyreg16.c
new file mode 100644
index 000000000..e488a6eee
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_modifyreg16.c
@@ -0,0 +1,85 @@
+/****************************************************************************
+ * arch/arm/src/common/up_modifyreg16.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <arch/irq.h>
+#include <nuttx/arch.h>
+
+#include "up_arch.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: modifyreg16
+ *
+ * Description:
+ * Atomically modify the specified bits in a memory mapped register
+ *
+ ****************************************************************************/
+
+void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits)
+{
+ irqstate_t flags;
+ uint16_t regval;
+
+ flags = irqsave();
+ regval = getreg16(addr);
+ regval &= ~clearbits;
+ regval |= setbits;
+ putreg16(regval, addr);
+ irqrestore(flags);
+}
diff --git a/nuttx/arch/arm/src/common/up_modifyreg32.c b/nuttx/arch/arm/src/common/up_modifyreg32.c
new file mode 100644
index 000000000..8b93f6b84
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_modifyreg32.c
@@ -0,0 +1,85 @@
+/****************************************************************************
+ * arch/arm/src/common/up_modifyreg32.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <arch/irq.h>
+#include <nuttx/arch.h>
+
+#include "up_arch.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: modifyreg32
+ *
+ * Description:
+ * Atomically modify the specified bits in a memory mapped register
+ *
+ ****************************************************************************/
+
+void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits)
+{
+ irqstate_t flags;
+ uint32_t regval;
+
+ flags = irqsave();
+ regval = getreg32(addr);
+ regval &= ~clearbits;
+ regval |= setbits;
+ putreg32(regval, addr);
+ irqrestore(flags);
+}
diff --git a/nuttx/arch/arm/src/common/up_modifyreg8.c b/nuttx/arch/arm/src/common/up_modifyreg8.c
new file mode 100644
index 000000000..2c9dbac25
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_modifyreg8.c
@@ -0,0 +1,85 @@
+/****************************************************************************
+ * arch/arm/src/common/up_modifyreg8.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <arch/irq.h>
+#include <nuttx/arch.h>
+
+#include "up_arch.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: modifyreg8
+ *
+ * Description:
+ * Atomically modify the specified bits in a memory mapped register
+ *
+ ****************************************************************************/
+
+void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits)
+{
+ irqstate_t flags;
+ uint8_t regval;
+
+ flags = irqsave();
+ regval = getreg8(addr);
+ regval &= ~clearbits;
+ regval |= setbits;
+ putreg8(regval, addr);
+ irqrestore(flags);
+}
diff --git a/nuttx/arch/arm/src/common/up_puts.c b/nuttx/arch/arm/src/common/up_puts.c
new file mode 100644
index 000000000..4e74f0cdc
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_puts.c
@@ -0,0 +1,75 @@
+/****************************************************************************
+ * arch/arm/src/common/up_puts.c
+ *
+ * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <nuttx/arch.h>
+
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_puts
+ *
+ * Description:
+ * This is a low-level helper function used to support debug.
+ *
+ ****************************************************************************/
+
+void up_puts(const char *str)
+{
+ while(*str)
+ {
+ up_putc(*str++);
+ }
+}
diff --git a/nuttx/arch/arm/src/common/up_releasestack.c b/nuttx/arch/arm/src/common/up_releasestack.c
new file mode 100644
index 000000000..407bd1b54
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_releasestack.c
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * arch/arm/src/common/up_releasestack.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sched.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+
+#include "os_internal.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_release_stack
+ *
+ * Description:
+ * A task has been stopped. Free all stack
+ * related resources retained int the defunct TCB.
+ *
+ ****************************************************************************/
+
+void up_release_stack(_TCB *dtcb)
+{
+ if (dtcb->stack_alloc_ptr)
+ {
+ sched_free(dtcb->stack_alloc_ptr);
+ dtcb->stack_alloc_ptr = NULL;
+ }
+
+ dtcb->adj_stack_size = 0;
+}
diff --git a/nuttx/arch/arm/src/common/up_udelay.c b/nuttx/arch/arm/src/common/up_udelay.c
new file mode 100644
index 000000000..d2d5b74d9
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_udelay.c
@@ -0,0 +1,129 @@
+/****************************************************************************
+ * arch/arm/src/common/up_udelay.c
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <nuttx/arch.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define CONFIG_BOARD_LOOPSPER100USEC ((CONFIG_BOARD_LOOPSPERMSEC+5)/10)
+#define CONFIG_BOARD_LOOPSPER10USEC ((CONFIG_BOARD_LOOPSPERMSEC+50)/100)
+#define CONFIG_BOARD_LOOPSPERUSEC ((CONFIG_BOARD_LOOPSPERMSEC+500)/1000)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_udelay
+ *
+ * Description:
+ * Delay inline for the requested number of microseconds. NOTE: Because
+ * of all of the setup, several microseconds will be lost before the actual
+ * timing looop begins. Thus, the delay will always be a few microseconds
+ * longer than requested.
+ *
+ * *** NOT multi-tasking friendly ***
+ *
+ * ASSUMPTIONS:
+ * The setting CONFIG_BOARD_LOOPSPERMSEC has been calibrated
+ *
+ ****************************************************************************/
+
+void up_udelay(useconds_t microseconds)
+{
+ volatile int i;
+
+ /* We'll do this a little at a time because we expect that the
+ * CONFIG_BOARD_LOOPSPERUSEC is very inaccurate during to truncation in
+ * the divisions of its calculation. We'll use the largest values that
+ * we can in order to prevent significant error buildup in the loops.
+ */
+
+ while (microseconds > 1000)
+ {
+ for (i = 0; i < CONFIG_BOARD_LOOPSPERMSEC; i++)
+ {
+ }
+ microseconds -= 1000;
+ }
+
+ while (microseconds > 100)
+ {
+ for (i = 0; i < CONFIG_BOARD_LOOPSPER100USEC; i++)
+ {
+ }
+ microseconds -= 100;
+ }
+
+ while (microseconds > 10)
+ {
+ for (i = 0; i < CONFIG_BOARD_LOOPSPER10USEC; i++)
+ {
+ }
+ microseconds -= 10;
+ }
+
+ while (microseconds > 0)
+ {
+ for (i = 0; i < CONFIG_BOARD_LOOPSPERUSEC; i++)
+ {
+ }
+ microseconds--;
+ }
+}
diff --git a/nuttx/arch/arm/src/common/up_usestack.c b/nuttx/arch/arm/src/common/up_usestack.c
new file mode 100644
index 000000000..f46be0cc9
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_usestack.c
@@ -0,0 +1,155 @@
+/****************************************************************************
+ * arch/arm/src/common/up_usestack.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/arch.h>
+
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Macros
+ ****************************************************************************/
+
+/* ARM requires at least a 4-byte stack alignment. For use with EABI and
+ * floating point, the stack must be aligned to 8-byte addresses.
+ */
+
+#ifndef CONFIG_STACK_ALIGNMENT
+
+/* The symbol __ARM_EABI__ is defined by GCC if EABI is being used. If you
+ * are not using GCC, make sure that CONFIG_STACK_ALIGNMENT is set correctly!
+ */
+
+# ifdef __ARM_EABI__
+# define CONFIG_STACK_ALIGNMENT 8
+# else
+# define CONFIG_STACK_ALIGNMENT 4
+# endif
+#endif
+
+/* Stack alignment macros */
+
+#define STACK_ALIGN_MASK (CONFIG_STACK_ALIGNMENT-1)
+#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK)
+#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_use_stack
+ *
+ * Description:
+ * Setup up stack-related information in the TCB
+ * using pre-allocated stack memory
+ *
+ * The following TCB fields must be initialized:
+ * adj_stack_size: Stack size after adjustment for hardware,
+ * processor, etc. This value is retained only for debug
+ * purposes.
+ * stack_alloc_ptr: Pointer to allocated stack
+ * adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The
+ * initial value of the stack pointer.
+ *
+ * Inputs:
+ * tcb: The TCB of new task
+ * stack_size: The allocated stack size.
+ *
+ ****************************************************************************/
+
+int up_use_stack(_TCB *tcb, void *stack, size_t stack_size)
+{
+ size_t top_of_stack;
+ size_t size_of_stack;
+
+ if (tcb->stack_alloc_ptr)
+ {
+ sched_free(tcb->stack_alloc_ptr);
+ }
+
+ /* Save the stack allocation */
+
+ tcb->stack_alloc_ptr = stack;
+
+ /* The ARM uses a push-down stack: the stack grows toward lower addresses
+ * in memory. The stack pointer register, points to the lowest, valid
+ * work address (the "top" of the stack). Items on the stack are
+ * referenced as positive word offsets from sp.
+ */
+
+ top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4;
+
+ /* The ARM stack must be aligned; 4 byte alignment for OABI and 8-byte
+ * alignment for EABI. If necessary top_of_stack must be rounded down
+ * to the next boundary
+ */
+
+ top_of_stack = STACK_ALIGN_DOWN(top_of_stack);
+
+ /* The size of the stack in bytes is then the difference between
+ * the top and the bottom of the stack (+4 because if the top
+ * is the same as the bottom, then the size is one 32-bit element).
+ * The size need not be aligned.
+ */
+
+ size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
+
+ /* Save the adjusted stack values in the _TCB */
+
+ tcb->adj_stack_ptr = (uint32_t*)top_of_stack;
+ tcb->adj_stack_size = size_of_stack;
+
+ return OK;
+}
diff --git a/nuttx/arch/arm/src/stm32/Kconfig b/nuttx/arch/arm/src/stm32/Kconfig
new file mode 100644
index 000000000..5d0d48f88
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/Kconfig
@@ -0,0 +1,1912 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+choice
+ prompt "STM32 Chip Selection"
+ default ARCH_CHIP_STM32F103ZET6
+ depends on ARCH_CHIP_STM32
+
+config ARCH_CHIP_STM32F103ZET6
+ bool "STM32F103ZET6"
+
+config ARCH_CHIP_STM32F103RET6
+ bool "STM32F103RET6"
+
+config ARCH_CHIP_STM32F103VCT6
+ bool "STM32F103VCT6"
+
+config ARCH_CHIP_STM32F105VBT7
+ bool "STM32F105VBT7"
+
+config ARCH_CHIP_STM32F107VC
+ bool "STM32F107VC"
+
+config ARCH_CHIP_STM32F207IG
+ bool "STM32F207IG"
+
+config ARCH_CHIP_STM32F405RG
+ bool "STM32F405RG"
+
+config ARCH_CHIP_STM32F405VG
+ bool "STM32F405VG"
+
+config ARCH_CHIP_STM32F405ZG
+ bool "STM32F405ZG"
+
+config ARCH_CHIP_STM32F407VE
+ bool "STM32F407VE"
+
+config ARCH_CHIP_STM32F407VG
+ bool "STM32F407VG"
+
+config ARCH_CHIP_STM32F407ZE
+ bool "STM32F407ZE"
+
+config ARCH_CHIP_STM32F407ZG
+ bool "STM32F407ZG"
+
+config ARCH_CHIP_STM32F407IE
+ bool "STM32F407IE"
+
+config ARCH_CHIP_STM32F407IG
+ bool "STM32F407IG"
+
+endchoice
+
+config STM32_STM32F10XX
+ bool
+ default y if ARCH_CHIP_STM32F103ZET6 || ARCH_CHIP_STM32F103RET6 || ARCH_CHIP_STM32F103VCT6 || ARCH_CHIP_STM32F105VBT7 || ARCH_CHIP_STM32F107VC
+
+config STM32_CONNECTIVITYLINE
+ bool
+ default y if ARCH_CHIP_STM32F105VBT7 || ARCH_CHIP_STM32F107VC
+
+config STM32_STM32F20XX
+ bool
+ default y if ARCH_CHIP_STM32F207IG
+
+config STM32_STM32F40XX
+ bool
+ default y if ARCH_CHIP_STM32F405RG || ARCH_CHIP_STM32F405VG || ARCH_CHIP_STM32F405ZG || ARCH_CHIP_STM32F407VE || ARCH_CHIP_STM32F407VG || ARCH_CHIP_STM32F407ZE || ARCH_CHIP_STM32F407ZG || ARCH_CHIP_STM32F407IE || ARCH_CHIP_STM32F407IE
+
+config ARCH_CORTEXM3
+ bool
+ default y if !STM32_STM32F40XX
+
+config ARCH_CORTEXM4
+ bool
+ default y if STM32_STM32F40XX
+
+menu "STM32 Peripheral Support"
+
+config STM32_ADC1
+ bool "ADC1"
+ default n
+
+config STM32_ADC2
+ bool "ADC2"
+ default n
+
+config STM32_ADC3
+ bool "ADC3"
+ default n
+
+config STM32_CRC
+ bool "CRC"
+ default n
+
+config STM32_DMA1
+ bool "DMA1"
+ default n
+
+config STM32_DMA2
+ bool "DMA2"
+ default n
+
+config STM32_BKP
+ bool "BKP"
+ default n
+ depends on STM32_STM32F10XX
+
+config STM32_BKPSRAM
+ bool "BKP RAM"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_CAN1
+ bool "CAN1"
+ default n
+
+config STM32_CAN2
+ bool "CAN2"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_CCMDATARAM
+ bool "CMD/DATA RAM"
+ default n
+ depends on STM32_STM32F40XX
+
+config STM32_CRYP
+ bool "CRYP"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_DAC1
+ bool "DAC1"
+ default n
+
+config STM32_DAC2
+ bool "DAC2"
+ default n
+
+config STM32_DCMI
+ bool "DCMI"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_ETHMAC
+ bool "Ethernet MAC"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_FSMC
+ bool "FSMC"
+ default n
+
+config STM32_HASH
+ bool "HASH"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_I2C1
+ bool "I2C1"
+ default n
+
+config STM32_I2C2
+ bool "I2C2"
+ default n
+
+config STM32_I2C3
+ bool "I2C3"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_IWDG
+ bool "IWDG"
+ default n
+
+config STM32_OTGFS
+ bool "OTG FS"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_OTGHS
+ bool "OTG HS"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_PWR
+ bool "PWR"
+ default n
+
+config STM32_RNG
+ bool "RNG"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_SDIO
+ bool "SDIO"
+ default n
+
+config STM32_SPI1
+ bool "SPI1"
+ default n
+
+config STM32_SPI2
+ bool "SPI2"
+ default n
+
+config STM32_SPI3
+ bool "SPI3"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_SPI4
+ bool "SPI4"
+ default n
+ depends on STM32_STM32F10XX
+
+config STM32_SYSCFG
+ bool "SYSCFG"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_TIM1
+ bool "TIM1"
+ default n
+
+config STM32_TIM2
+ bool "TIM2"
+ default n
+
+config STM32_TIM3
+ bool "TIM3"
+ default n
+
+config STM32_TIM4
+ bool "TIM4"
+ default n
+
+config STM32_TIM5
+ bool "TIM5"
+ default n
+
+config STM32_TIM6
+ bool "TIM6"
+ default n
+
+config STM32_TIM7
+ bool "TIM7"
+ default n
+
+config STM32_TIM8
+ bool "TIM8"
+ default n
+
+config STM32_TIM9
+ bool "TIM9"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_TIM10
+ bool "TIM10"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_TIM11
+ bool "TIM11"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_TIM12
+ bool "TIM12"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_TIM13
+ bool "TIM13"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_TIM14
+ bool "TIM14"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_USART1
+ bool "USART1"
+ default n
+
+config STM32_USART2
+ bool "USART2"
+ default n
+
+config STM32_USART3
+ bool "USART3"
+ default n
+
+config STM32_UART4
+ bool "UART4"
+ default n
+
+config STM32_UART5
+ bool "UART5"
+ default n
+
+config STM32_USART6
+ bool "USART6"
+ default n
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+
+config STM32_USB
+ bool "USB Device"
+ default n
+ depends on STM32_STM32F10XX
+
+config STM32_WWDG
+ bool "WWDG"
+ default n
+
+endmenu
+
+config STM32_ADC
+ bool
+ default y if STM32_ADC1 || STM32_ADC2 || STM32_ADC3
+
+config STM32_DAC
+ bool
+ default y if STM32_DAC1 || STM32_ADC2
+
+config STM32_SPI
+ bool
+ default y if STM32_SPI1 || STM32_SPI2 || STM32_SPI3 || STM32_SPI4
+
+config STM32_DMA
+ bool
+ default y if STM32_DMA1 || STM32_DMA2
+
+config STM32_CAN
+ bool
+ default y if STM32_CAN1 || STM32_CAN2
+
+choice
+ prompt "TIM1 Alternate Pin Mappings"
+ depends on STM32_STM32F10XX && STM32_TIM1
+ default STM32_TIM1_NO_REMAP
+
+config STM32_TIM1_NO_REMAP
+ bool "No pin remapping"
+
+config STM32_TIM1_FULL_REMAP
+ bool "Full pin remapping"
+
+config STM32_TIM1_PARTIAL_REMAP
+ bool "Partial pin remapping"
+
+endchoice
+
+choice
+ prompt "TIM2 Alternate Pin Mappings"
+ depends on STM32_STM32F10XX && STM32_TIM2
+ default STM32_TIM2_NO_REMAP
+
+config STM32_TIM2_NO_REMAP
+ bool "No pin remapping"
+
+config STM32_TIM2_FULL_REMAP
+ bool "Full pin remapping"
+
+config STM32_TIM2_PARTIAL_REMAP_1
+ bool "Partial pin remapping #1"
+
+config STM32_TIM2_PARTIAL_REMAP_2
+ bool "Partial pin remapping #2"
+
+endchoice
+
+choice
+ prompt "TIM3 Alternate Pin Mappings"
+ depends on STM32_STM32F10XX && STM32_TIM3
+ default STM32_TIM3_NO_REMAP
+
+config STM32_TIM3_NO_REMAP
+ bool "No pin remapping"
+
+config STM32_TIM3_FULL_REMAP
+ bool "Full pin remapping"
+
+config STM32_TIM3_PARTIAL_REMAP
+ bool "Partial pin remapping"
+
+endchoice
+
+config STM32_TIM4_REMAP
+ bool "TIM4 Alternate Pin Mapping"
+ default n
+ depends on STM32_STM32F10XX && STM32_TIM4
+
+config STM32_USART1_REMAP
+ bool "USART1 Alternate Pin Mapping"
+ default n
+ depends on STM32_STM32F10XX && STM32_USART1
+
+config STM32_USART2_REMAP
+ bool "USART2 Alternate Pin Mapping"
+ default n
+ depends on STM32_STM32F10XX && STM32_USART2
+
+choice
+ prompt "USART3 Alternate Pin Mappings"
+ depends on STM32_STM32F10XX && STM32_USART3
+ default STM32_USART3_NO_REMAP
+
+config STM32_USART3_NO_REMAP
+ bool "No pin remapping"
+
+config STM32_USART3_FULL_REMAP
+ bool "Full pin remapping"
+
+config STM32_USART3_PARTIAL_REMAP
+ bool "Partial pin remapping"
+
+endchoice
+
+config STM32_SPI1_REMAP
+ bool "SPI1 Alternate Pin Mapping"
+ default n
+ depends on STM32_STM32F10XX && STM32_SPI1
+
+config STM32_SPI3_REMAP
+ bool "SPI3 Alternate Pin Mapping"
+ default n
+ depends on STM32_STM32F10XX && STM32_SPI3
+
+config STM32_I2C1_REMAP
+ bool "I2C1 Alternate Pin Mapping"
+ default n
+ depends on STM32_STM32F10XX && STM32_I2C1
+
+choice
+ prompt "CAN1 Alternate Pin Mappings"
+ depends on STM32_STM32F10XX && STM32_CAN1
+ default STM32_CAN1_NO_REMAP
+
+config STM32_CAN1_NO_REMAP
+ bool "No pin remapping"
+
+config STM32_CAN1_FULL_REMAP
+ bool "Full pin remapping"
+
+config STM32_CAN1_PARTIAL_REMAP
+ bool "Partial pin remapping"
+
+endchoice
+
+config STM32_CAN2_REMAP
+ bool "CAN2 Alternate Pin Mapping"
+ default n
+ depends on STM32_STM32F10XX && STM32_CAN2
+
+choice
+ prompt "JTAG Configuration"
+ default STM32_JTAG_DISABLE
+ ---help---
+ JTAG Enable settings (by default JTAG-DP and SW-DP are disabled)
+
+config STM32_JTAG_DISABLE
+ bool "Disable all JTAG clocking"
+
+config STM32_JTAG_FULL_ENABLE
+ bool "Enable full SWJ (JTAG-DP + SW-DP)"
+
+config STM32_JTAG_NOJNTRST_ENABLE
+ bool "Enable full SWJ (JTAG-DP + SW-DP) but without JNTRST"
+
+config STM32_JTAG_SW_ENABLE
+ bool "Set JTAG-DP disabled and SW-DP enabled"
+
+endchoice
+
+config STM32_FORCEPOWER
+ bool "Force power"
+ default n
+ ---help---
+ Timer and I2C devices may need to the following to force power to be applied
+ unconditionally at power up. (Otherwise, the device is powered when it is
+ initialized).
+
+config ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG
+ bool "Custom clock configuration"
+ default n
+ ---help---
+ Enables special, board-specific STM32 clock configuration.
+
+config STM32_CCMEXCLUDE
+ bool "Exclude CCM SRAM from the heap"
+ depends on STM32_STM32F20XX || STM32_STM32F40XX
+ default y if STM32_DMA1 || STM32_DMA2
+ ---help---
+ Exclude CCM SRAM from the HEAP because it cannot be used for DMA.
+
+config STM32_FSMC_SRAM
+ bool "External SRAM on FSMC"
+ default n
+ depends on FSMC
+ ---help---
+ In addition to internal SRAM, SRAM may also be available through the FSMC.
+
+config HEAP2_BASE
+ hex "FSMC SRAM base address"
+ default 0x00000000
+ depends on STM32_FSMC_SRAM
+ ---help---
+ The base address of the SRAM in the FSMC address space.
+
+config HEAP2_END
+ hex "FSMC SRAM end+1 address"
+ default 0x00000000
+ depends on STM32_FSMC_SRAM
+ ---help---
+ The end (+1) of the SRAM in the FSMC address space
+
+config ARCH_FPU
+ bool "FPU support"
+ default y
+ depends on ARCH_CORTEXM4
+ ---help---
+ Build in support for the ARM Cortex-M4 FPU. Only the STM3240xxx supports
+ a floating point unit (FPU)
+
+config STM32_TIM1_PWM
+ bool "TIM1 PWM"
+ default n
+ depends on STM32_TIM1
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM1
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM1_CHANNEL
+ int "TIM1 PWM Output Channel"
+ default 1
+ depends on STM32_TIM1_PWM
+ ---help---
+ If TIM1 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM2_PWM
+ bool "TIM2 PWM"
+ default n
+ depends on STM32_TIM2
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM2
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM2_CHANNEL
+ int "TIM2 PWM Output Channel"
+ default 1
+ depends on STM32_TIM2_PWM
+ ---help---
+ If TIM2 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM3_PWM
+ bool "TIM3 PWM"
+ default n
+ depends on STM32_TIM3
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM3
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM3_CHANNEL
+ int "TIM3 PWM Output Channel"
+ default 1
+ depends on STM32_TIM3_PWM
+ ---help---
+ If TIM3 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM4_PWM
+ bool "TIM4 PWM"
+ default n
+ depends on STM32_TIM4
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM4
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM4_CHANNEL
+ int "TIM4 PWM Output Channel"
+ default 1
+ depends on STM32_TIM4_PWM
+ ---help---
+ If TIM4 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM5_PWM
+ bool "TIM5 PWM"
+ default n
+ depends on STM32_TIM5
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM5
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM5_CHANNEL
+ int "TIM5 PWM Output Channel"
+ default 1
+ depends on STM32_TIM5_PWM
+ ---help---
+ If TIM5 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM8_PWM
+ bool "TIM8 PWM"
+ default n
+ depends on STM32_TIM8
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM8
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM8_CHANNEL
+ int "TIM8 PWM Output Channel"
+ default 1
+ depends on STM32_TIM8_PWM
+ ---help---
+ If TIM8 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM9_PWM
+ bool "TIM9 PWM"
+ default n
+ depends on STM32_TIM9
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM9
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM9_CHANNEL
+ int "TIM9 PWM Output Channel"
+ default 1
+ depends on STM32_TIM9_PWM
+ ---help---
+ If TIM9 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM10_PWM
+ bool "TIM10 PWM"
+ default n
+ depends on STM32_TIM10
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM10
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM10_CHANNEL
+ int "TIM10 PWM Output Channel"
+ default 1
+ depends on STM32_TIM10_PWM
+ ---help---
+ If TIM10 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM11_PWM
+ bool "TIM11 PWM"
+ default n
+ depends on STM32_TIM11
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM11
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM11_CHANNEL
+ int "TIM11 PWM Output Channel"
+ default 1
+ depends on STM32_TIM11_PWM
+ ---help---
+ If TIM11 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM12_PWM
+ bool "TIM12 PWM"
+ default n
+ depends on STM32_TIM12
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM12
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM12_CHANNEL
+ int "TIM12 PWM Output Channel"
+ default 1
+ depends on STM32_TIM12_PWM
+ ---help---
+ If TIM12 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM13_PWM
+ bool "TIM13 PWM"
+ default n
+ depends on STM32_TIM13
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM13
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM13_CHANNEL
+ int "TIM13 PWM Output Channel"
+ default 1
+ depends on STM32_TIM13_PWM
+ ---help---
+ If TIM13 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM14_PWM
+ bool "TIM14 PWM"
+ default n
+ depends on STM32_TIM14
+ ---help---
+ Reserve timer 1 for use by PWM
+
+ Timer devices may be used for different purposes. One special purpose is
+ to generate modulated outputs for such things as motor control. If STM32_TIM14
+ is defined then THIS following may also be defined to indicate that
+ the timer is intended to be used for pulsed output modulation.
+
+config STM32_TIM14_CHANNEL
+ int "TIM14 PWM Output Channel"
+ default 1
+ depends on STM32_TIM14_PWM
+ ---help---
+ If TIM14 is enabled for PWM usage, you also need specifies the timer output
+ channel {1,..,4}
+
+config STM32_TIM1_ADC
+ bool "TIM1 ADC"
+ default n
+ depends on STM32_TIM1 && STM32_ADC
+ ---help---
+ Reserve timer 1 for use by ADC
+
+ Timer devices may be used for different purposes. If STM32_TIM1 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for ADC conversion. Note that ADC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the ADC, but then you also have to configure which ADC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM1 ADC channel"
+ default STM32_TIM1_ADC1
+ depends on STM32_TIM1_ADC
+
+config STM32_TIM1_ADC1
+ bool "TIM1 ADC channel 1"
+ ---help---
+ Reserve TIM1 to trigger ADC1
+
+config STM32_TIM1_ADC2
+ bool "TIM1 ADC channel 2"
+ ---help---
+ Reserve TIM1 to trigger ADC2
+
+config STM32_TIM1_ADC3
+ bool "TIM1 ADC channel 3"
+ ---help---
+ Reserve TIM1 to trigger ADC3
+
+endchoice
+
+config STM32_TIM2_ADC
+ bool "TIM2 ADC"
+ default n
+ depends on STM32_TIM2 && STM32_ADC
+ ---help---
+ Reserve timer 1 for use by ADC
+
+ Timer devices may be used for different purposes. If STM32_TIM2 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for ADC conversion. Note that ADC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the ADC, but then you also have to configure which ADC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM2 ADC channel"
+ default STM32_TIM2_ADC1
+ depends on STM32_TIM2_ADC
+
+config STM32_TIM2_ADC1
+ bool "TIM2 ADC channel 1"
+ ---help---
+ Reserve TIM2 to trigger ADC1
+
+config STM32_TIM2_ADC2
+ bool "TIM2 ADC channel 2"
+ ---help---
+ Reserve TIM2 to trigger ADC2
+
+config STM32_TIM2_ADC3
+ bool "TIM2 ADC channel 3"
+ ---help---
+ Reserve TIM2 to trigger ADC3
+
+endchoice
+
+config STM32_TIM3_ADC
+ bool "TIM3 ADC"
+ default n
+ depends on STM32_TIM3 && STM32_ADC
+ ---help---
+ Reserve timer 1 for use by ADC
+
+ Timer devices may be used for different purposes. If STM32_TIM3 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for ADC conversion. Note that ADC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the ADC, but then you also have to configure which ADC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM3 ADC channel"
+ default STM32_TIM3_ADC1
+ depends on STM32_TIM3_ADC
+
+config STM32_TIM3_ADC1
+ bool "TIM3 ADC channel 1"
+ ---help---
+ Reserve TIM3 to trigger ADC1
+
+config STM32_TIM3_ADC2
+ bool "TIM3 ADC channel 2"
+ ---help---
+ Reserve TIM3 to trigger ADC2
+
+config STM32_TIM3_ADC3
+ bool "TIM3 ADC channel 3"
+ ---help---
+ Reserve TIM3 to trigger ADC3
+
+endchoice
+
+config STM32_TIM4_ADC
+ bool "TIM4 ADC"
+ default n
+ depends on STM32_TIM4 && STM32_ADC
+ ---help---
+ Reserve timer 1 for use by ADC
+
+ Timer devices may be used for different purposes. If STM32_TIM4 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for ADC conversion. Note that ADC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the ADC, but then you also have to configure which ADC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM4 ADC channel"
+ default STM32_TIM4_ADC1
+ depends on STM32_TIM4_ADC
+
+config STM32_TIM4_ADC1
+ bool "TIM4 ADC channel 1"
+ ---help---
+ Reserve TIM4 to trigger ADC1
+
+config STM32_TIM4_ADC2
+ bool "TIM4 ADC channel 2"
+ ---help---
+ Reserve TIM4 to trigger ADC2
+
+config STM32_TIM4_ADC3
+ bool "TIM4 ADC channel 3"
+ ---help---
+ Reserve TIM4 to trigger ADC3
+
+endchoice
+
+config STM32_TIM5_ADC
+ bool "TIM5 ADC"
+ default n
+ depends on STM32_TIM5 && STM32_ADC
+ ---help---
+ Reserve timer 1 for use by ADC
+
+ Timer devices may be used for different purposes. If STM32_TIM5 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for ADC conversion. Note that ADC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the ADC, but then you also have to configure which ADC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM5 ADC channel"
+ default STM32_TIM5_ADC1
+ depends on STM32_TIM5_ADC
+
+config STM32_TIM5_ADC1
+ bool "TIM5 ADC channel 1"
+ ---help---
+ Reserve TIM5 to trigger ADC1
+
+config STM32_TIM5_ADC2
+ bool "TIM5 ADC channel 2"
+ ---help---
+ Reserve TIM5 to trigger ADC2
+
+config STM32_TIM5_ADC3
+ bool "TIM5 ADC channel 3"
+ ---help---
+ Reserve TIM5 to trigger ADC3
+
+endchoice
+
+config STM32_TIM8_ADC
+ bool "TIM8 ADC"
+ default n
+ depends on STM32_TIM8 && STM32_ADC
+ ---help---
+ Reserve timer 1 for use by ADC
+
+ Timer devices may be used for different purposes. If STM32_TIM8 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for ADC conversion. Note that ADC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the ADC, but then you also have to configure which ADC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM8 ADC channel"
+ default STM32_TIM8_ADC1
+ depends on STM32_TIM8_ADC
+
+config STM32_TIM8_ADC1
+ bool "TIM8 ADC channel 1"
+ ---help---
+ Reserve TIM8 to trigger ADC1
+
+config STM32_TIM8_ADC2
+ bool "TIM8 ADC channel 2"
+ ---help---
+ Reserve TIM8 to trigger ADC2
+
+config STM32_TIM8_ADC3
+ bool "TIM8 ADC channel 3"
+ ---help---
+ Reserve TIM8 to trigger ADC3
+
+endchoice
+
+config STM32_TIM1_DAC
+ bool "TIM1 DAC"
+ default n
+ depends on STM32_TIM1 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM1 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM1 DAC channel"
+ default STM32_TIM1_DAC1
+ depends on STM32_TIM1_DAC
+
+config STM32_TIM1_DAC1
+ bool "TIM1 DAC channel 1"
+ ---help---
+ Reserve TIM1 to trigger DAC1
+
+config STM32_TIM1_DAC2
+ bool "TIM1 DAC channel 2"
+ ---help---
+ Reserve TIM1 to trigger DAC2
+
+endchoice
+
+config STM32_TIM2_DAC
+ bool "TIM2 DAC"
+ default n
+ depends on STM32_TIM2 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM2 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM2 DAC channel"
+ default STM32_TIM2_DAC1
+ depends on STM32_TIM2_DAC
+
+config STM32_TIM2_DAC1
+ bool "TIM2 DAC channel 1"
+ ---help---
+ Reserve TIM2 to trigger DAC1
+
+config STM32_TIM2_DAC2
+ bool "TIM2 DAC channel 2"
+ ---help---
+ Reserve TIM2 to trigger DAC2
+
+endchoice
+
+config STM32_TIM3_DAC
+ bool "TIM3 DAC"
+ default n
+ depends on STM32_TIM3 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM3 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM3 DAC channel"
+ default STM32_TIM3_DAC1
+ depends on STM32_TIM3_DAC
+
+config STM32_TIM3_DAC1
+ bool "TIM3 DAC channel 1"
+ ---help---
+ Reserve TIM3 to trigger DAC1
+
+config STM32_TIM3_DAC2
+ bool "TIM3 DAC channel 2"
+ ---help---
+ Reserve TIM3 to trigger DAC2
+
+endchoice
+
+config STM32_TIM4_DAC
+ bool "TIM4 DAC"
+ default n
+ depends on STM32_TIM4 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM4 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM4 DAC channel"
+ default STM32_TIM4_DAC1
+ depends on STM32_TIM4_DAC
+
+config STM32_TIM4_DAC1
+ bool "TIM4 DAC channel 1"
+ ---help---
+ Reserve TIM4 to trigger DAC1
+
+config STM32_TIM4_DAC2
+ bool "TIM4 DAC channel 2"
+ ---help---
+ Reserve TIM4 to trigger DAC2
+
+endchoice
+
+config STM32_TIM5_DAC
+ bool "TIM5 DAC"
+ default n
+ depends on STM32_TIM5 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM5 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM5 DAC channel"
+ default STM32_TIM5_DAC1
+ depends on STM32_TIM5_DAC
+
+config STM32_TIM5_DAC1
+ bool "TIM5 DAC channel 1"
+ ---help---
+ Reserve TIM5 to trigger DAC1
+
+config STM32_TIM5_DAC2
+ bool "TIM5 DAC channel 2"
+ ---help---
+ Reserve TIM5 to trigger DAC2
+
+endchoice
+
+config STM32_TIM6_DAC
+ bool "TIM6 DAC"
+ default n
+ depends on STM32_TIM6 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM6 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM6 DAC channel"
+ default STM32_TIM6_DAC1
+ depends on STM32_TIM6_DAC
+
+config STM32_TIM6_DAC1
+ bool "TIM6 DAC channel 1"
+ ---help---
+ Reserve TIM6 to trigger DAC1
+
+config STM32_TIM6_DAC2
+ bool "TIM6 DAC channel 2"
+ ---help---
+ Reserve TIM6 to trigger DAC2
+
+endchoice
+
+config STM32_TIM7_DAC
+ bool "TIM7 DAC"
+ default n
+ depends on STM32_TIM7 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM7 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM7 DAC channel"
+ default STM32_TIM7_DAC1
+ depends on STM32_TIM7_DAC
+
+config STM32_TIM7_DAC1
+ bool "TIM7 DAC channel 1"
+ ---help---
+ Reserve TIM7 to trigger DAC1
+
+config STM32_TIM7_DAC2
+ bool "TIM7 DAC channel 2"
+ ---help---
+ Reserve TIM7 to trigger DAC2
+
+endchoice
+
+config STM32_TIM8_DAC
+ bool "TIM8 DAC"
+ default n
+ depends on STM32_TIM8 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM8 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM8 DAC channel"
+ default STM32_TIM8_DAC1
+ depends on STM32_TIM8_DAC
+
+config STM32_TIM8_DAC1
+ bool "TIM8 DAC channel 1"
+ ---help---
+ Reserve TIM8 to trigger DAC1
+
+config STM32_TIM8_DAC2
+ bool "TIM8 DAC channel 2"
+ ---help---
+ Reserve TIM8 to trigger DAC2
+
+endchoice
+
+config STM32_TIM9_DAC
+ bool "TIM9 DAC"
+ default n
+ depends on STM32_TIM9 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM9 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM9 DAC channel"
+ default STM32_TIM9_DAC1
+ depends on STM32_TIM9_DAC
+
+config STM32_TIM9_DAC1
+ bool "TIM9 DAC channel 1"
+ ---help---
+ Reserve TIM9 to trigger DAC1
+
+config STM32_TIM9_DAC2
+ bool "TIM9 DAC channel 2"
+ ---help---
+ Reserve TIM9 to trigger DAC2
+
+endchoice
+
+config STM32_TIM10_DAC
+ bool "TIM10 DAC"
+ default n
+ depends on STM32_TIM10 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM10 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM10 DAC channel"
+ default STM32_TIM10_DAC1
+ depends on STM32_TIM10_DAC
+
+config STM32_TIM10_DAC1
+ bool "TIM10 DAC channel 1"
+ ---help---
+ Reserve TIM10 to trigger DAC1
+
+config STM32_TIM10_DAC2
+ bool "TIM10 DAC channel 2"
+ ---help---
+ Reserve TIM10 to trigger DAC2
+
+endchoice
+
+config STM32_TIM11_DAC
+ bool "TIM11 DAC"
+ default n
+ depends on STM32_TIM11 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM11 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM11 DAC channel"
+ default STM32_TIM11_DAC1
+ depends on STM32_TIM11_DAC
+
+config STM32_TIM11_DAC1
+ bool "TIM11 DAC channel 1"
+ ---help---
+ Reserve TIM11 to trigger DAC1
+
+config STM32_TIM11_DAC2
+ bool "TIM11 DAC channel 2"
+ ---help---
+ Reserve TIM11 to trigger DAC2
+
+endchoice
+
+config STM32_TIM12_DAC
+ bool "TIM12 DAC"
+ default n
+ depends on STM32_TIM12 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM12 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM12 DAC channel"
+ default STM32_TIM12_DAC1
+ depends on STM32_TIM12_DAC
+
+config STM32_TIM12_DAC1
+ bool "TIM12 DAC channel 1"
+ ---help---
+ Reserve TIM12 to trigger DAC1
+
+config STM32_TIM12_DAC2
+ bool "TIM12 DAC channel 2"
+ ---help---
+ Reserve TIM12 to trigger DAC2
+
+endchoice
+
+config STM32_TIM13_DAC
+ bool "TIM13 DAC"
+ default n
+ depends on STM32_TIM13 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM13 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM13 DAC channel"
+ default STM32_TIM13_DAC1
+ depends on STM32_TIM13_DAC
+
+config STM32_TIM13_DAC1
+ bool "TIM13 DAC channel 1"
+ ---help---
+ Reserve TIM13 to trigger DAC1
+
+config STM32_TIM13_DAC2
+ bool "TIM13 DAC channel 2"
+ ---help---
+ Reserve TIM13 to trigger DAC2
+
+endchoice
+
+config STM32_TIM14_DAC
+ bool "TIM14 DAC"
+ default n
+ depends on STM32_TIM14 && STM32_DAC
+ ---help---
+ Reserve timer 1 for use by DAC
+
+ Timer devices may be used for different purposes. If STM32_TIM14 is
+ defined then the following may also be defined to indicate that the
+ timer is intended to be used for DAC conversion. Note that DAC usage
+ requires two definition: Not only do you have to assign the timer
+ for used by the DAC, but then you also have to configure which DAC
+ channel it is assigned to.
+
+choice
+ prompt "Select TIM14 DAC channel"
+ default STM32_TIM14_DAC1
+ depends on STM32_TIM14_DAC
+
+config STM32_TIM14_DAC1
+ bool "TIM14 DAC channel 1"
+ ---help---
+ Reserve TIM14 to trigger DAC1
+
+config STM32_TIM14_DAC2
+ bool "TIM14 DAC channel 2"
+ ---help---
+ Reserve TIM14 to trigger DAC2
+
+endchoice
+
+menu "USART1 Configuration"
+ depends on STM32_USART1
+
+config USART1_SERIAL_CONSOLE
+ bool "USART1 serial console"
+ default y
+ ---help---
+ Selects the USART1 for the console and ttys0 (default is the USART1).
+
+config USART1_RXBUFSIZE
+ int "USART1 Rx buffer size"
+ default 256
+ ---help---
+ Characters are buffered as received. This specific the size of the receive
+ buffer.
+
+config USART1_TXBUFSIZE
+ int "USART1 Tx buffer size"
+ default 256
+ ---help---
+ Characters are buffered before being sent. This specific the size of the
+ transmit buffer
+
+config USART1_BAUD
+ int "USART1 BAUD"
+ default 11520
+ ---help---
+ The configured BAUD of the UART
+
+config USART1_BITS
+ int "USART1 number of bits"
+ default 8
+ ---help---
+ The number of bits. Must be either 7 or 8.
+
+config USART1_PARITY
+ int "USART1 parity"
+ default 0
+ ---help---
+ 0=no parity, 1=odd parity, 2=even parity
+
+config USART1_2STOP
+ bool "USART1 two stop bits"
+ default n
+ ---help---
+ Two stop bits
+
+config USART1_RXDMA
+ bool "USART1 Rx DMA"
+ default n
+ depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA2
+ ---help---
+ In high data rate usage, Rx DMA may eliminate Rx overrun errors
+
+endmenu
+
+menu "USART2 Configuration"
+ depends on STM32_USART2
+
+config USART2_SERIAL_CONSOLE
+ bool "USART2 serial console"
+ default y if !STM32_USART1
+ ---help---
+ Selects the USART2 for the console and ttys0 (default is the USART2).
+
+config USART2_RXBUFSIZE
+ int "USART2 Rx buffer size"
+ default 256
+ ---help---
+ Characters are buffered as received. This specific the size of the receive
+ buffer.
+
+config USART2_TXBUFSIZE
+ int "USART2 Tx buffer size"
+ default 256
+ ---help---
+ Characters are buffered before being sent. This specific the size of the
+ transmit buffer
+
+config USART2_BAUD
+ int "USART2 BAUD"
+ default 11520
+ ---help---
+ The configured BAUD of the UART
+
+config USART2_BITS
+ int "USART2 number of bits"
+ default 8
+ ---help---
+ The number of bits. Must be either 7 or 8.
+
+config USART2_PARITY
+ int "USART2 parity"
+ default 0
+ ---help---
+ 0=no parity, 1=odd parity, 2=even parity
+
+config USART2_2STOP
+ bool "USART2 two stop bits"
+ default n
+ ---help---
+ Two stop bits
+
+config USART2_RXDMA
+ bool "USART2 Rx DMA"
+ default n
+ depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA1
+ ---help---
+ In high data rate usage, Rx DMA may eliminate Rx overrun errors
+
+endmenu
+
+menu "USART3 Configuration"
+ depends on STM32_USART3
+
+config USART3_SERIAL_CONSOLE
+ bool "USART3 serial console"
+ default y if !STM32_USART1 && !STM32_USART2
+ ---help---
+ Selects the USART3 for the console and ttys0 (default is the USART3).
+
+config USART3_RXBUFSIZE
+ int "USART3 Rx buffer size"
+ default 256
+ ---help---
+ Characters are buffered as received. This specific the size of the receive
+ buffer.
+
+config USART3_TXBUFSIZE
+ int "USART3 Tx buffer size"
+ default 256
+ ---help---
+ Characters are buffered before being sent. This specific the size of the
+ transmit buffer
+
+config USART3_BAUD
+ int "USART3 BAUD"
+ default 11520
+ ---help---
+ The configured BAUD of the UART
+
+config USART3_BITS
+ int "USART3 number of bits"
+ default 8
+ ---help---
+ The number of bits. Must be either 7 or 8.
+
+config USART3_PARITY
+ int "USART3 parity"
+ default 0
+ ---help---
+ 0=no parity, 1=odd parity, 2=even parity
+
+config USART3_2STOP
+ bool "USART3 two stop bits"
+ default n
+ ---help---
+ Two stop bits
+
+config USART3_RXDMA
+ bool "USART3 Rx DMA"
+ default n
+ depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA1
+ ---help---
+ In high data rate usage, Rx DMA may eliminate Rx overrun errors
+
+endmenu
+
+menu "UART4 Configuration"
+ depends on STM32_UART4
+
+config USART4_SERIAL_CONSOLE
+ bool "UART4 serial console"
+ default y if !STM32_USART1 && !STM32_USART2 && !STM32_USART3
+ ---help---
+ Selects the UART4 for the console and ttys0 (default is the USART1).
+
+config USART4_RXBUFSIZE
+ int "UART4 Rx buffer size"
+ default 256
+ ---help---
+ Characters are buffered as received. This specific the size of the receive
+ buffer.
+
+config USART4_TXBUFSIZE
+ int "UART4 Tx buffer size"
+ default 256
+ ---help---
+ Characters are buffered before being sent. This specific the size of the
+ transmit buffer
+
+config USART4_BAUD
+ int "UART4 BAUD"
+ default 11520
+ ---help---
+ The configured BAUD of the UART
+
+config USART4_BITS
+ int "UART4 number of bits"
+ default 8
+ ---help---
+ The number of bits. Must be either 7 or 8.
+
+config USART4_PARITY
+ int "UART4 parity"
+ default 0
+ ---help---
+ 0=no parity, 1=odd parity, 2=even parity
+
+config USART4_2STOP
+ bool "UART4 two stop bits"
+ default n
+ ---help---
+ Two stop bits
+
+config USART4_RXDMA
+ bool "USART4 Rx DMA"
+ default n
+ depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA1
+ ---help---
+ In high data rate usage, Rx DMA may eliminate Rx overrun errors
+
+endmenu
+
+menu "UART5 Configuration"
+ depends on STM32_UART5
+
+config USART5_SERIAL_CONSOLE
+ bool "UART5 serial console"
+ default y if !STM32_USART1 && !STM32_USART2 && !STM32_USART3 && !STM32_UART4
+ ---help---
+ Selects the UART5 for the console and ttys0 (default is the USART1).
+
+config USART5_RXBUFSIZE
+ int "USART5 Rx buffer size"
+ default 256
+ ---help---
+ Characters are buffered as received. This specific the size of the receive
+ buffer.
+
+config USART5_TXBUFSIZE
+ int "UART5 Tx buffer size"
+ default 256
+ ---help---
+ Characters are buffered before being sent. This specific the size of the
+ transmit buffer
+
+config USART5_BAUD
+ int "UART5 BAUD"
+ default 11520
+ ---help---
+ The configured BAUD of the UART
+
+config USART5_BITS
+ int "UART5 number of bits"
+ default 8
+ ---help---
+ The number of bits. Must be either 7 or 8.
+
+config USART5_PARITY
+ int "UART5 parity"
+ default 0
+ ---help---
+ 0=no parity, 1=odd parity, 2=even parity
+
+config USART5_2STOP
+ bool "UART5 two stop bits"
+ default n
+ ---help---
+ Two stop bits
+
+config USART5_RXDMA
+ bool "USART5 Rx DMA"
+ default n
+ depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA1
+ ---help---
+ In high data rate usage, Rx DMA may eliminate Rx overrun errors
+
+endmenu
+
+menu "USART6 Configuration"
+ depends on STM32_USART6
+
+config USART6_SERIAL_CONSOLE
+ bool "USART6 serial console"
+ default y if !STM32_USART1 && !STM32_USART2 && !STM32_USART3 && !STM32_UART4 && !STM32_UART5
+ ---help---
+ Selects the USART6 for the console and ttys0 (default is the USART6).
+
+config USART6_RXBUFSIZE
+ int "USART6 Rx buffer size"
+ default 256
+ ---help---
+ Characters are buffered as received. This specific the size of the receive
+ buffer.
+
+config USART6_TXBUFSIZE
+ int "USART6 Tx buffer size"
+ default 256
+ ---help---
+ Characters are buffered before being sent. This specific the size of the
+ transmit buffer
+
+config USART6_BAUD
+ int "USART6 BAUD"
+ default 11520
+ ---help---
+ The configured BAUD of the UART
+
+config USART6_BITS
+ int "USART6 number of bits"
+ default 8
+ ---help---
+ The number of bits. Must be either 7 or 8.
+
+config USART6_PARITY
+ int "USART6 parity"
+ default 0
+ ---help---
+ 0=no parity, 1=odd parity, 2=even parity
+
+config USART6_2STOP
+ bool "USART6 two stop bits"
+ default n
+ ---help---
+ Two stop bits
+
+config USART6_RXDMA
+ bool "USART6 Rx DMA"
+ default n
+ depends on STM32_STM32F40XX && ARCH_DMA && STM32_DMA2
+ ---help---
+ In high data rate usage, Rx DMA may eliminate Rx overrun errors
+
+endmenu
+
+config SERIAL_TERMIOS
+ bool "Serial driver TERMIOS supported"
+ depends on STM32_USART1 || STM32_USART2 || STM32_USART3 || STM32_UART4 || STM32_UART5 || STM32_USART6
+ default n
+ ---help---
+ Serial driver supports termios.h interfaces (tcsetattr, tcflush, etc.).
+ If this is not defined, then the terminal settings (baud, parity, etc).
+ are not configurable at runtime; serial streams cannot be flushed, etc..
+
+menu "SPI Configuration"
+ depends on STM32_SPI
+
+config STM32_SPI_INTERRUPTS
+ bool "Interrupt driver SPI"
+ default n
+ ---help---
+ Select to enable interrupt driven SPI support. Non-interrupt-driven,
+ poll-waiting is recommended if the interrupt rate would be to high in
+ the interrupt driven case.
+
+config STM32_SPI_DMA
+ bool "SPI DMA"
+ default n
+ ---help---
+ Use DMA to improve SPI transfer performance. Cannot be used with STM32_SPI_INTERRUPT.
+
+endmenu
+
+menu "SDIO Configuration"
+ depends on STM32_SDIO
+
+config SDIO_DMA
+ bool "Support DMA data transfers"
+ default y if STM32_DMA2
+ depends on STM32_DMA2
+ ---help---
+ Support DMA data transfers. Requires STM32_SDIO and config STM32_DMA2.
+
+config SDIO_PRI
+ hex "SDIO interrupt priority"
+ default 128
+ ---help---
+ Select SDIO interrupt prority. Default: 128.
+
+config SDIO_DMAPRIO
+ hex "SDIO DMA priority"
+ default 0x00001000
+ ---help---
+ Select SDIO DMA prority. Options: 0x00000000 low, 0x00001000 medium,
+ 0x00002000 high, 0x00003000 very high. Default: medium.
+
+config SDIO_WIDTH_D1_ONLY
+ bool "Use D1 only"
+ default n
+ ---help---
+ Select 1-bit transfer mode. Default: 4-bit transfer mode.
+
+endmenu
+
+menu "Ethernet MAC configuration"
+
+config STM32_PHYADDR
+ int "PHY address"
+ ---help---
+ The 5-bit address of the PHY on the board
+
+config STM32_MII
+ bool "Use MII interface"
+ default n
+ ---help---
+ Support Ethernet MII interface.
+
+config STM32_MII_MCO2
+ bool "Use MC02 as MII clock"
+ default n
+ depends on STM32_MII
+ ---help---
+ Use MCO2 to clock the MII interface. Default: Use MC01
+
+config STM32_AUTONEG
+ bool "Use autonegtiation"
+ default y
+ ---help---
+ Use PHY autonegotion to determine speed and mode
+
+config STM32_ETHFD
+ bool "Full duplex"
+ default n
+ depends on !STM32_AUTONEG
+ ---help---
+ If STM32_AUTONEG is not defined, then this may be defined to select full duplex
+ mode. Default: half-duplex
+
+config STM32_ETH100MBPS
+ bool "100 Mbps"
+ default n
+ depends on !STM32_AUTONEG
+ ---help---
+ If STM32_AUTONEG is not defined, then this may be defined to select 100 MBps
+ speed. Default: 10 Mbps
+
+config STM32_PHYSR
+ hex "PHY status register address"
+ depends on STM32_AUTONEG
+ ---help---
+ This must be provided if STM32_AUTONEG is defined. The PHY status register
+ address may diff from PHY to PHY. This configuration sets the address of
+ the PHY status register.
+
+config STM32_PHYSR_SPEED
+ hex "PHY speed mask"
+ depends on STM32_AUTONEG
+ ---help---
+ This must be provided if STM32_AUTONEG is defined. This provides bit mask
+ indicating 10 or 100MBps speed.
+
+config STM32_PHYSR_100MBPS
+ hex "PHY 100Mbps speed value"
+ depends on STM32_AUTONEG
+ ---help---
+ This must be provided if STM32_AUTONEG is defined. This provides the value
+ of the speed bit(s) indicating 100MBps speed.
+
+config STM32_PHYSR_MODE
+ hex "PHY mode mask"
+ depends on STM32_AUTONEG
+ ---help---
+ This must be provided if STM32_AUTONEG is defined. This provide bit mask
+ indicating full or half duplex modes.
+
+config STM32_PHYSR_FULLDUPLEX
+ hex "PHY full duplex mode value"
+ depends on STM32_AUTONEG
+ ---help---
+ This must be provided if STM32_AUTONEG is defined. This provides the
+ value of the mode bits indicating full duplex mode.
+
+config STM32_ETH_PTP
+ bool "Precision Time Protocol (PTP)"
+ default n
+ ---help---
+ Precision Time Protocol (PTP). Not supported but some hooks are indicated
+ with this condition.
+
+endmenu
+
+config STM32_RMII
+ bool
+ default y if !STM32_MII
+
+config STM32_MII_MCO1
+ bool
+ default y if !STM32_MII_MCO2
+ depends on STM32_MII
diff --git a/nuttx/arch/arm/src/stm32/Make.defs b/nuttx/arch/arm/src/stm32/Make.defs
new file mode 100644
index 000000000..1deb23189
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/Make.defs
@@ -0,0 +1,143 @@
+############################################################################
+# arch/arm/src/stm32/Make.defs
+#
+# Copyright (C) 2009, 2011-2012 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.
+#
+############################################################################
+
+ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y)
+HEAD_ASRC =
+else
+HEAD_ASRC = stm32_vectors.S
+endif
+
+CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S
+CMN_CSRCS = up_assert.c up_blocktask.c up_copystate.c \
+ up_createstack.c up_mdelay.c up_udelay.c up_exit.c \
+ up_initialize.c up_initialstate.c up_interruptcontext.c \
+ up_memfault.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c \
+ up_releasepending.c up_releasestack.c up_reprioritizertr.c \
+ up_schedulesigaction.c up_sigdeliver.c up_unblocktask.c \
+ up_usestack.c up_doirq.c up_hardfault.c up_svcall.c \
+ up_stackcheck.c
+
+ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y)
+CMN_ASRCS += up_exception.S
+CMN_CSRCS += up_vectors.c
+endif
+
+ifeq ($(CONFIG_DEBUG_STACK),y)
+CMN_CSRCS += up_checkstack.c
+endif
+
+ifeq ($(CONFIG_ARCH_FPU),y)
+CMN_ASRCS += up_fpu.S
+endif
+
+ifeq ($(CONFIG_ARCH_MEMCPY),y)
+CMN_ASRCS += memcpy.S
+endif
+
+CHIP_ASRCS =
+CHIP_CSRCS = stm32_allocateheap.c stm32_start.c stm32_rcc.c stm32_lse.c \
+ stm32_lsi.c stm32_gpio.c stm32_exti_gpio.c stm32_flash.c stm32_irq.c \
+ stm32_timerisr.c stm32_dma.c stm32_lowputc.c stm32_serial.c \
+ stm32_spi.c stm32_sdio.c stm32_tim.c stm32_i2c.c stm32_waste.c
+
+ifeq ($(CONFIG_USBDEV),y)
+ifeq ($(CONFIG_STM32_USB),y)
+CMN_CSRCS += stm32_usbdev.c
+endif
+ifeq ($(CONFIG_STM32_OTGFS),y)
+CMN_CSRCS += stm32_otgfsdev.c
+endif
+endif
+
+ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y)
+CHIP_ASRCS += stm32_vectors.S
+endif
+
+ifneq ($(CONFIG_IDLE_CUSTOM),y)
+CHIP_CSRCS += stm32_idle.c
+endif
+
+CHIP_CSRCS += stm32_pmstop.c stm32_pmstandby.c stm32_pmsleep.c
+
+ifneq ($(CONFIG_PM_CUSTOMINIT),y)
+CHIP_CSRCS += stm32_pminitialize.c
+endif
+
+ifeq ($(CONFIG_STM32_ETHMAC),y)
+CHIP_CSRCS += stm32_eth.c
+endif
+
+ifeq ($(CONFIG_STM32_PWR),y)
+CHIP_CSRCS += stm32_pwr.c
+endif
+
+ifeq ($(CONFIG_RTC),y)
+CHIP_CSRCS += stm32_rtc.c
+ifeq ($(CONFIG_RTC_ALARM),y)
+CHIP_CSRCS += stm32_exti_alarm.c
+endif
+endif
+
+ifeq ($(CONFIG_ADC),y)
+CHIP_CSRCS += stm32_adc.c
+endif
+
+ifeq ($(CONFIG_DAC),y)
+CHIP_CSRCS += stm32_dac.c
+endif
+
+ifeq ($(CONFIG_PWM),y)
+CHIP_CSRCS += stm32_pwm.c
+endif
+
+ifeq ($(CONFIG_QENCODER),y)
+CHIP_CSRCS += stm32_qencoder.c
+endif
+
+ifeq ($(CONFIG_CAN),y)
+CHIP_CSRCS += stm32_can.c
+endif
+
+ifeq ($(CONFIG_STM32_IWDG),y)
+CHIP_CSRCS += stm32_iwdg.c
+endif
+
+ifeq ($(CONFIG_STM32_WWDG),y)
+CHIP_CSRCS += stm32_wwdg.c
+endif
+
+ifeq ($(CONFIG_DEBUG),y)
+CHIP_CSRCS += stm32_dumpgpio.c
+endif
diff --git a/nuttx/arch/arm/src/stm32/chip.h b/nuttx/arch/arm/src/stm32/chip.h
new file mode 100644
index 000000000..cc3ee1f96
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip.h
@@ -0,0 +1,100 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_CHIP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+/* Include the chip capabilities file */
+
+#include <arch/stm32/chip.h>
+
+/* Include the chip pin configuration file */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# if defined(CONFIG_STM32_VALUELINE)
+# include "chip/stm32f100_pinmap.h"
+# elif defined(CONFIG_ARCH_CHIP_STM32F103ZET6)
+# include "chip/stm32f103ze_pinmap.h"
+# elif defined(CONFIG_ARCH_CHIP_STM32F103RET6)
+# include "chip/stm32f103re_pinmap.h"
+# elif defined(CONFIG_ARCH_CHIP_STM32F103VCT6)
+# include "chip/stm32f103vc_pinmap.h"
+# elif defined(CONFIG_ARCH_CHIP_STM32F105VBT7)
+# include "chip/stm32f105vb_pinmap.h"
+# elif defined(CONFIG_ARCH_CHIP_STM32F107VC)
+# include "chip/stm32f107vc_pinmap.h"
+# else
+# error "Unsupported STM32F10XXX chip"
+# endif
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/stm32f20xxx_pinmap.h"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32f40xxx_pinmap.h"
+#else
+# error "No pinmap file for this STM32 chip"
+#endif
+
+/* If the common ARMv7-M vector handling logic is used, then include the
+ * required vector definitions as well.
+ */
+
+#ifdef CONFIG_ARMV7M_CMNVECTOR
+# if defined(CONFIG_STM32_STM32F10XX)
+# include "chip/stm32f10xxx_vectors.h"
+# elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/stm32f20xxx_vectors.h"
+# elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32f40xxx_vectors.h"
+# else
+# error "No vector file for this STM32 family"
+# endif
+#endif
+
+/* Include the chip memory map. */
+
+#include "chip/stm32_memorymap.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_adc.h b/nuttx/arch/arm/src/stm32/chip/stm32_adc.h
new file mode 100644
index 000000000..218b11aa5
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_adc.h
@@ -0,0 +1,564 @@
+/****************************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_adc.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_CHIP_STM32_ADC_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_ADC_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/****************************************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************************************/
+
+/* Register Offsets *********************************************************************************/
+
+#define STM32_ADC_SR_OFFSET 0x0000 /* ADC status register (32-bit) */
+#define STM32_ADC_CR1_OFFSET 0x0004 /* ADC control register 1 (32-bit) */
+#define STM32_ADC_CR2_OFFSET 0x0008 /* ADC control register 2 (32-bit) */
+#define STM32_ADC_SMPR1_OFFSET 0x000c /* ADC sample time register 1 (32-bit) */
+#define STM32_ADC_SMPR2_OFFSET 0x0010 /* ADC sample time register 2 (32-bit) */
+#define STM32_ADC_JOFR1_OFFSET 0x0014 /* ADC injected channel data offset register 1 (32-bit) */
+#define STM32_ADC_JOFR2_OFFSET 0x0018 /* ADC injected channel data offset register 2 (32-bit) */
+#define STM32_ADC_JOFR3_OFFSET 0x001c /* ADC injected channel data offset register 3 (32-bit) */
+#define STM32_ADC_JOFR4_OFFSET 0x0020 /* ADC injected channel data offset register 4 (32-bit) */
+#define STM32_ADC_HTR_OFFSET 0x0024 /* ADC watchdog high threshold register (32-bit) */
+#define STM32_ADC_LTR_OFFSET 0x0028 /* ADC watchdog low threshold register (32-bit) */
+#define STM32_ADC_SQR1_OFFSET 0x002c /* ADC regular sequence register 1 (32-bit) */
+#define STM32_ADC_SQR2_OFFSET 0x0030 /* ADC regular sequence register 2 (32-bit) */
+#define STM32_ADC_SQR3_OFFSET 0x0034 /* ADC regular sequence register 3 (32-bit) */
+#define STM32_ADC_JSQR_OFFSET 0x0038 /* ADC injected sequence register (32-bit) */
+#define STM32_ADC_JDR1_OFFSET 0x003c /* ADC injected data register 1 (32-bit) */
+#define STM32_ADC_JDR2_OFFSET 0x0040 /* ADC injected data register 1 (32-bit) */
+#define STM32_ADC_JDR3_OFFSET 0x0044 /* ADC injected data register 1 (32-bit) */
+#define STM32_ADC_JDR4_OFFSET 0x0048 /* ADC injected data register 1 (32-bit) */
+#define STM32_ADC_DR_OFFSET 0x004c /* ADC regular data register (32-bit) */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_ADC_CSR_OFFSET 0x0000 /* Common status register */
+# define STM32_ADC_CCR_OFFSET 0x0004 /* Common control register */
+# define STM32_ADC_CDR_OFFSET 0x0008 /* Data register for dual and triple modes */
+#endif
+
+/* Register Addresses *******************************************************************************/
+
+#if STM32_NADC > 0
+# define STM32_ADC1_SR (STM32_ADC1_BASE+STM32_ADC_SR_OFFSET)
+# define STM32_ADC1_CR1 (STM32_ADC1_BASE+STM32_ADC_CR1_OFFSET)
+# define STM32_ADC1_CR2 (STM32_ADC1_BASE+STM32_ADC_CR2_OFFSET)
+# define STM32_ADC1_SMPR1 (STM32_ADC1_BASE+STM32_ADC_SMPR1_OFFSET)
+# define STM32_ADC1_SMPR2 (STM32_ADC1_BASE+STM32_ADC_SMPR2_OFFSET)
+# define STM32_ADC1_JOFR1 (STM32_ADC1_BASE+STM32_ADC_JOFR1_OFFSET)
+# define STM32_ADC1_JOFR2 (STM32_ADC1_BASE+STM32_ADC_JOFR2_OFFSET)
+# define STM32_ADC1_JOFR3 (STM32_ADC1_BASE+STM32_ADC_JOFR3_OFFSET)
+# define STM32_ADC1_JOFR4 (STM32_ADC1_BASE+STM32_ADC_JOFR4_OFFSET)
+# define STM32_ADC1_HTR (STM32_ADC1_BASE+STM32_ADC_HTR_OFFSET)
+# define STM32_ADC1_LTR (STM32_ADC1_BASE+STM32_ADC_LTR_OFFSET)
+# define STM32_ADC1_SQR1 (STM32_ADC1_BASE+STM32_ADC_SQR1_OFFSET)
+# define STM32_ADC1_SQR2 (STM32_ADC1_BASE+STM32_ADC_SQR2_OFFSET)
+# define STM32_ADC1_SQR3 (STM32_ADC1_BASE+STM32_ADC_SQR3_OFFSET)
+# define STM32_ADC1_JSQR (STM32_ADC1_BASE+STM32_ADC_JSQR_OFFSET)
+# define STM32_ADC1_JDR1 (STM32_ADC1_BASE+STM32_ADC_JDR1_OFFSET)
+# define STM32_ADC1_JDR2 (STM32_ADC1_BASE+STM32_ADC_JDR2_OFFSET)
+# define STM32_ADC1_JDR3 (STM32_ADC1_BASE+STM32_ADC_JDR3_OFFSET)
+# define STM32_ADC1_JDR4 (STM32_ADC1_BASE+STM32_ADC_JDR4_OFFSET)
+# define STM32_ADC1_DR (STM32_ADC1_BASE+STM32_ADC_DR_OFFSET)
+#endif
+
+#if STM32_NADC > 1
+# define STM32_ADC2_SR (STM32_ADC2_BASE+STM32_ADC_SR_OFFSET)
+# define STM32_ADC2_CR1 (STM32_ADC2_BASE+STM32_ADC_CR1_OFFSET)
+# define STM32_ADC2_CR2 (STM32_ADC2_BASE+STM32_ADC_CR2_OFFSET)
+# define STM32_ADC2_SMPR1 (STM32_ADC2_BASE+STM32_ADC_SMPR1_OFFSET)
+# define STM32_ADC2_SMPR2 (STM32_ADC2_BASE+STM32_ADC_SMPR2_OFFSET)
+# define STM32_ADC2_JOFR1 (STM32_ADC2_BASE+STM32_ADC_JOFR1_OFFSET)
+# define STM32_ADC2_JOFR2 (STM32_ADC2_BASE+STM32_ADC_JOFR2_OFFSET)
+# define STM32_ADC2_JOFR3 (STM32_ADC2_BASE+STM32_ADC_JOFR3_OFFSET)
+# define STM32_ADC2_JOFR4 (STM32_ADC2_BASE+STM32_ADC_JOFR4_OFFSET)
+# define STM32_ADC2_HTR (STM32_ADC2_BASE+STM32_ADC_HTR_OFFSET)
+# define STM32_ADC2_LTR (STM32_ADC2_BASE+STM32_ADC_LTR_OFFSET)
+# define STM32_ADC2_SQR1 (STM32_ADC2_BASE+STM32_ADC_SQR1_OFFSET)
+# define STM32_ADC2_SQR2 (STM32_ADC2_BASE+STM32_ADC_SQR2_OFFSET)
+# define STM32_ADC2_SQR3 (STM32_ADC2_BASE+STM32_ADC_SQR3_OFFSET)
+# define STM32_ADC2_JSQR (STM32_ADC2_BASE+STM32_ADC_JSQR_OFFSET)
+# define STM32_ADC2_JDR1 (STM32_ADC2_BASE+STM32_ADC_JDR1_OFFSET)
+# define STM32_ADC2_JDR2 (STM32_ADC2_BASE+STM32_ADC_JDR2_OFFSET)
+# define STM32_ADC2_JDR3 (STM32_ADC2_BASE+STM32_ADC_JDR3_OFFSET)
+# define STM32_ADC2_JDR4 (STM32_ADC2_BASE+STM32_ADC_JDR4_OFFSET)
+# define STM32_ADC2_DR (STM32_ADC2_BASE+STM32_ADC_DR_OFFSET)
+#endif
+
+#if STM32_NADC > 2
+# define STM32_ADC3_SR (STM32_ADC3_BASE+STM32_ADC_SR_OFFSET)
+# define STM32_ADC3_CR1 (STM32_ADC3_BASE+STM32_ADC_CR1_OFFSET)
+# define STM32_ADC3_CR2 (STM32_ADC3_BASE+STM32_ADC_CR2_OFFSET)
+# define STM32_ADC3_SMPR1 (STM32_ADC3_BASE+STM32_ADC_SMPR1_OFFSET)
+# define STM32_ADC3_SMPR2 (STM32_ADC3_BASE+STM32_ADC_SMPR2_OFFSET)
+# define STM32_ADC3_JOFR1 (STM32_ADC3_BASE+STM32_ADC_JOFR1_OFFSET)
+# define STM32_ADC3_JOFR2 (STM32_ADC3_BASE+STM32_ADC_JOFR2_OFFSET)
+# define STM32_ADC3_JOFR3 (STM32_ADC3_BASE+STM32_ADC_JOFR3_OFFSET)
+# define STM32_ADC3_JOFR4 (STM32_ADC3_BASE+STM32_ADC_JOFR4_OFFSET)
+# define STM32_ADC3_HTR (STM32_ADC3_BASE+STM32_ADC_HTR_OFFSET)
+# define STM32_ADC3_LTR (STM32_ADC3_BASE+STM32_ADC_LTR_OFFSET)
+# define STM32_ADC3_SQR1 (STM32_ADC3_BASE+STM32_ADC_SQR1_OFFSET)
+# define STM32_ADC3_SQR2 (STM32_ADC3_BASE+STM32_ADC_SQR2_OFFSET)
+# define STM32_ADC3_SQR3 (STM32_ADC3_BASE+STM32_ADC_SQR3_OFFSET)
+# define STM32_ADC3_JSQR (STM32_ADC3_BASE+STM32_ADC_JSQR_OFFSET)
+# define STM32_ADC3_JDR1 (STM32_ADC3_BASE+STM32_ADC_JDR1_OFFSET)
+# define STM32_ADC3_JDR2 (STM32_ADC3_BASE+STM32_ADC_JDR2_OFFSET)
+# define STM32_ADC3_JDR3 (STM32_ADC3_BASE+STM32_ADC_JDR3_OFFSET)
+# define STM32_ADC3_JDR4 (STM32_ADC3_BASE+STM32_ADC_JDR4_OFFSET)
+# define STM32_ADC3_DR (STM32_ADC3_BASE+STM32_ADC_DR_OFFSET)
+#endif
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_ADC_CSR (STM32_ADCCMN_BASE+STM32_ADC_CSR_OFFSET)
+# define STM32_ADC_CCR (STM32_ADCCMN_BASE+STM32_ADC_CCR_OFFSET)
+# define STM32_ADC_CDR (STM32_ADCCMN_BASE+STM32_ADC_CDR_OFFSET)
+#endif
+
+/* Register Bitfield Definitions ********************************************************************/
+
+/* ADC status register */
+
+#define ADC_SR_AWD (1 << 0) /* Bit 0 : Analog watchdog flag */
+#define ADC_SR_EOC (1 << 1) /* Bit 1 : End of conversion */
+#define ADC_SR_JEOC (1 << 2) /* Bit 2 : Injected channel end of conversion */
+#define ADC_SR_JSTRT (1 << 3) /* Bit 3 : Injected channel Start flag */
+#define ADC_SR_STRT (1 << 4) /* Bit 4 : Regular channel Start flag */
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define ADC_SR_OVR (1 << 5) /* Bit 5 : Overrun */
+#endif
+
+/* ADC control register 1 */
+
+#define ADC_CR1_AWDCH_SHIFT (0) /* Bits 4-0: Analog watchdog channel select bits */
+#define ADC_CR1_AWDCH_MASK (0x1f << ADC_CR1_AWDCH_SHIFT)
+
+#define ADC_CR1_EOCIE (1 << 5) /* Bit 5: Interrupt enable for EOC */
+#define ADC_CR1_AWDIE (1 << 6) /* Bit 6: Analog Watchdog interrupt enable */
+#define ADC_CR1_JEOCIE (1 << 7) /* Bit 7: Interrupt enable for injected channels */
+#define ADC_CR1_SCAN (1 << 8) /* Bit 8: Scan mode */
+#define ADC_CR1_AWDSGL (1 << 9) /* Bit 9: Enable the watchdog on a single channel in scan mode */
+#define ADC_CR1_JAUTO (1 << 10) /* Bit 10: Automatic Injected Group conversion */
+#define ADC_CR1_DISCEN (1 << 11) /* Bit 11: Discontinuous mode on regular channels */
+#define ADC_CR1_JDISCEN (1 << 12) /* Bit 12: Discontinuous mode on injected channels */
+
+#define ADC_CR1_DISCNUM_SHIFT (13) /* Bits 15-13: Discontinuous mode channel count */
+#define ADC_CR1_DISCNUM_MASK (0x07 << ADC_CR1_DISCNUM_SHIFT)
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ADC_CR1_DUALMOD_SHIFT (16) /* Bits 19-16: Dual mode selection */
+# define ADC_CR1_DUALMOD_MASK (0x0f << ADC_CR1_DUALMOD_SHIFT)
+# define ADC_CR1_IND (0 << ADC_CR1_DUALMOD_SHIFT) /* 0000: Independent mode */
+# define ADC_CR1_RSIS (1 << ADC_CR1_DUALMOD_SHIFT) /* 0001: Combined regular simultaneous + injected simultaneous mode */
+# define ADC_CR1_RSAT (2 << ADC_CR1_DUALMOD_SHIFT) /* 0010: Combined regular simultaneous + alternate trigger mode */
+# define ADC_CR1_ISFI (3 << ADC_CR1_DUALMOD_SHIFT) /* 0011: Combined injected simultaneous + fast interleaved mode */
+# define ADC_CR1_ISFL (4 << ADC_CR1_DUALMOD_SHIFT) /* 0100: Combined injected simultaneous + slow Interleaved mode */
+# define ADC_CR1_IS (5 << ADC_CR1_DUALMOD_SHIFT) /* 0101: Injected simultaneous mode only */
+# define ADC_CR1_RS (6 << ADC_CR1_DUALMOD_SHIFT) /* 0110: Regular simultaneous mode only */
+# define ADC_CR1_FI (7 << ADC_CR1_DUALMOD_SHIFT) /* 0111: Fast interleaved mode only */
+# define ADC_CR1_SI (8 << ADC_CR1_DUALMOD_SHIFT) /* 1000: Slow interleaved mode only */
+# define ADC_CR1_AT (9 << ADC_CR1_DUALMOD_SHIFT) /* 1001: Alternate trigger mode only */
+#endif
+
+#define ADC_CR1_JAWDEN (1 << 22) /* Bit 22: Analog watchdog enable on injected channels */
+#define ADC_CR1_AWDEN (1 << 23) /* Bit 23: Analog watchdog enable on regular channels */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define ACD_CR1_RES_SHIFT (24) /* Bits 24-25: Resolution */
+# define ACD_CR1_RES_MASK (3 << ACD_CR1_RES_SHIFT)
+# define ACD_CR1_RES_12BIT (0 << ACD_CR1_RES_SHIFT) /* 15 ADCCLK clyes */
+# define ACD_CR1_RES_10BIT (1 << ACD_CR1_RES_SHIFT) /* 13 ADCCLK clyes */
+# define ACD_CR1_RES_8BIT (2 << ACD_CR1_RES_SHIFT) /* 11 ADCCLK clyes */
+# define ACD_CR1_RES_6BIT (3 << ACD_CR1_RES_SHIFT) /* 9 ADCCLK clyes */
+# define ADC_CR1_OVRIE (1 << 26) /* Bit 26: Overrun interrupt enable */
+#endif
+
+/* ADC control register 2 */
+
+#define ADC_CR2_ADON (1 << 0) /* Bit 0: A/D Converter ON / OFF */
+#define ADC_CR2_CONT (1 << 1) /* Bit 1: Continuous Conversion */
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ADC_CR2_CAL (1 << 2) /* Bit 2: A/D Calibration */
+#endif
+
+#define ADC_CR2_RSTCAL (1 << 3) /* Bit 3: Reset Calibration */
+#define ADC_CR2_DMA (1 << 8) /* Bit 8: Direct Memory access mode */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define ADC_CR2_DDS (1 << 9) /* Bit 9: DMA disable selection (for single ADC mode) */
+# define ADC_CR2_EOCS (1 << 10) /* Bit 10: End of conversion selection */
+#endif
+
+#define ADC_CR2_ALIGN (1 << 11) /* Bit 11: Data Alignment */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ /* Bits 12-15: Reserved */
+# define ADC_CR2_JEXTSEL_SHIFT (16) /* Bits 16-19: External event select for injected group */
+# define ADC_CR2_JEXTSEL_MASK (15 << ADC_CR2_JEXTSEL_SHIFT)
+# define ADC_CR2_JEXTSEL_T1CC4 (0 << ADC_CR2_JEXTSEL_SHIFT) /* 0000: Timer 1 CC4 event */
+# define ADC_CR2_JEXTSEL_T1TRGO (1 << ADC_CR2_JEXTSEL_SHIFT) /* 0001: Timer 1 TRGO event */
+# define ADC_CR2_JEXTSEL_T2CC1 (2 << ADC_CR2_JEXTSEL_SHIFT) /* 0010: Timer 2 CC1 event */
+# define ADC_CR2_JEXTSEL_T2TRGO (3 << ADC_CR2_JEXTSEL_SHIFT) /* 0011: Timer 2 TRGO event */
+# define ADC_CR2_JEXTSEL_T3CC2 (4 << ADC_CR2_JEXTSEL_SHIFT) /* 0100: Timer 3 CC2 event */
+# define ADC_CR2_JEXTSEL_T3CC4 (5 << ADC_CR2_JEXTSEL_SHIFT) /* 0101: Timer 3 CC4 event */
+# define ADC_CR2_JEXTSEL_T4CC1 (6 << ADC_CR2_JEXTSEL_SHIFT) /* 0110: Timer 4 CC1 event */
+# define ADC_CR2_JEXTSEL_T4CC2 (7 << ADC_CR2_JEXTSEL_SHIFT) /* 0111: Timer 4 CC2 event */
+# define ADC_CR2_JEXTSEL_T4CC3 (8 << ADC_CR2_JEXTSEL_SHIFT) /* 1000: Timer 4 CC3 event */
+# define ADC_CR2_JEXTSEL_T4TRGO (9 << ADC_CR2_JEXTSEL_SHIFT) /* 1001: Timer 4 TRGO event */
+# define ADC_CR2_JEXTSEL_T5CC4 (10 << ADC_CR2_JEXTSEL_SHIFT) /* 1010: Timer 5 CC4 event */
+# define ADC_CR2_JEXTSEL_T5TRGO (11 << ADC_CR2_JEXTSEL_SHIFT) /* 1011: Timer 5 TRGO event */
+# define ADC_CR2_JEXTSEL_T8CC2 (12 << ADC_CR2_JEXTSEL_SHIFT) /* 1100: Timer 8 CC2 event */
+# define ADC_CR2_JEXTSEL_T8CC3 (13 << ADC_CR2_JEXTSEL_SHIFT) /* 1101: Timer 8 CC3 event */
+# define ADC_CR2_JEXTSEL_T8CC4 (14 << ADC_CR2_JEXTSEL_SHIFT) /* 1110: Timer 8 CC4 event */
+# define ADC_CR2_JEXTSEL_EXTI (15 << ADC_CR2_JEXTSEL_SHIFT) /* 1111: EXTI line15 */
+
+# define ACD_CR2_JEXTEN_SHIFT (20) /* Bits 20-21: External trigger enable for injected channels */
+# define ACD_CR2_JEXTEN_MASK (3 << ACD_CR2_JEXTEN_SHIFT)
+# define ACD_CR2_JEXTEN_NONE (0 << ACD_CR2_JEXTEN_SHIFT) /* 00: Trigger detection disabled */
+# define ACD_CR2_JEXTEN_RISING (1 << ACD_CR2_JEXTEN_SHIFT) /* 01: Trigger detection on the rising edge */
+# define ACD_CR2_JEXTEN_FALLING (2 << ACD_CR2_JEXTEN_SHIFT) /* 10: Trigger detection on the falling edge */
+# define ACD_CR2_JEXTEN_BOTH (3 << ACD_CR2_JEXTEN_SHIFT) /* 11: Trigger detection on both the rising and falling edges */
+
+# define ADC_CR2_JSWSTART (1 << 22) /* Bit 22: Start Conversion of injected channels */
+ /* Bit 23: Reserved, must be kept at reset value. */
+# define ADC_CR2_EXTSEL_SHIFT (24) /* Bits 24-27: External Event Select for regular group */
+# define ADC_CR2_EXTSEL_MASK (15 << ADC_CR2_EXTSEL_SHIFT)
+# define ADC_CR2_EXTSEL_T1CC1 (0 << ADC_CR2_EXTSEL_SHIFT) /* 0000: Timer 1 CC1 event */
+# define ADC_CR2_EXTSEL_T1CC2 (1 << ADC_CR2_EXTSEL_SHIFT) /* 0001: Timer 1 CC2 event */
+# define ADC_CR2_EXTSEL_T1CC3 (2 << ADC_CR2_EXTSEL_SHIFT) /* 0010: Timer 1 CC3 event */
+# define ADC_CR2_EXTSEL_T2CC2 (3 << ADC_CR2_EXTSEL_SHIFT) /* 0011: Timer 2 CC2 event */
+# define ADC_CR2_EXTSEL_T2CC3 (4 << ADC_CR2_EXTSEL_SHIFT) /* 0100: Timer 2 CC3 event */
+# define ADC_CR2_EXTSEL_T2CC4 (5 << ADC_CR2_EXTSEL_SHIFT) /* 0101: Timer 2 CC4 event */
+# define ADC_CR2_EXTSEL_T2TRGO (6 << ADC_CR2_EXTSEL_SHIFT) /* 0110: Timer 2 TRGO event */
+# define ADC_CR2_EXTSEL_T3CC1 (7 << ADC_CR2_EXTSEL_SHIFT) /* 0111: Timer 3 CC1 event */
+# define ADC_CR2_EXTSEL_T3TRGO (8 << ADC_CR2_EXTSEL_SHIFT) /* 1000: Timer 3 TRGO event */
+# define ADC_CR2_EXTSEL_T4CC4 (9 << ADC_CR2_EXTSEL_SHIFT) /* 1001: Timer 4 CC4 event */
+# define ADC_CR2_EXTSEL_T5CC1 (10 << ADC_CR2_EXTSEL_SHIFT) /* 1010: Timer 5 CC1 event */
+# define ADC_CR2_EXTSEL_T5CC2 (11 << ADC_CR2_EXTSEL_SHIFT) /* 1011: Timer 5 CC2 event */
+# define ADC_CR2_EXTSEL_T5CC3 (12 << ADC_CR2_EXTSEL_SHIFT) /* 1100: Timer 5 CC3 event */
+# define ADC_CR2_EXTSEL_T8CC1 (13 << ADC_CR2_EXTSEL_SHIFT) /* 1101: Timer 8 CC1 event */
+# define ADC_CR2_EXTSEL_T8TRGO (14 << ADC_CR2_EXTSEL_SHIFT) /* 1110: Timer 8 TRGO event */
+# define ADC_CR2_EXTSEL_EXTI (15 << ADC_CR2_EXTSEL_SHIFT) /* 1111: EXTI line11 */
+
+# define ACD_CR2_EXTEN_SHIFT (28) /* Bits 28-29: External trigger enable for regular channels */
+# define ACD_CR2_EXTEN_MASK (3 << ACD_CR2_EXTEN_SHIFT)
+# define ACD_CR2_EXTEN_NONE (0 << ACD_CR2_EXTEN_SHIFT) /* 00: Trigger detection disabled */
+# define ACD_CR2_EXTEN_RISING (1 << ACD_CR2_EXTEN_SHIFT) /* 01: Trigger detection on the rising edge */
+# define ACD_CR2_EXTEN_FALLING (2 << ACD_CR2_EXTEN_SHIFT) /* 10: Trigger detection on the falling edge */
+# define ACD_CR2_EXTEN_BOTH (3 << ACD_CR2_EXTEN_SHIFT) /* 11: Trigger detection on both the rising and falling edges */
+
+# define ADC_CR2_SWSTART (1 << 30) /* Bit 30: Start Conversion of regular channels */
+
+#else
+# define ADC_CR2_JEXTSEL_SHIFT (12) /* Bits 12-14: External event select for injected group */
+# define ADC_CR2_JEXTSEL_MASK (7 << ADC_CR2_JEXTSEL_SHIFT)
+# define ADC_CR2_JEXTSEL_T1TRGO (0 << ADC_CR2_JEXTSEL_SHIFT) /* 000: Timer 1 TRGO event */
+# define ADC_CR2_JEXTSEL_T1CC4 (1 << ADC_CR2_JEXTSEL_SHIFT) /* 001: Timer 1 CC4 event */
+# define ADC_CR2_JEXTSEL_T2TRGO (2 << ADC_CR2_JEXTSEL_SHIFT) /* 010: Timer 2 TRGO event */
+# define ADC_CR2_JEXTSEL_T2CC1 (3 << ADC_CR2_JEXTSEL_SHIFT) /* 011: Timer 2 CC1 event */
+# define ADC_CR2_JEXTSEL_T3CC4 (4 << ADC_CR2_JEXTSEL_SHIFT) /* 100: Timer 3 CC4 event */
+# define ADC_CR2_JEXTSEL_T4TRGO (5 << ADC_CR2_JEXTSEL_SHIFT) /* 101: Timer 4 TRGO event */
+# define ADC_CR2_JEXTSEL_EXTI15 (6 << ADC_CR2_JEXTSEL_SHIFT) /* 110: EXTI line15 */
+# define ADC_CR2_JEXTSEL_SWSTART (7 << ADC_CR2_JEXTSEL_SHIFT) /* 111: JSWSTART */
+
+# define ADC_CR2_JEXTTRIG (1 << 15) /* Bit 15: External Trigger Conversion mode for injected channels */
+# define ADC_CR2_EXTSEL_SHIFT (17) /* Bits 19-17: External Event Select for regular group */
+# define ADC_CR2_EXTSEL_MASK (7 << ADC_CR2_EXTSEL_SHIFT)
+# define ADC_CR2_EXTSEL_T1CC1 (0 << ADC_CR2_EXTSEL_SHIFT) /* 000: Timer 1 CC1 event */
+# define ADC_CR2_EXTSEL_T1CC2 (1 << ADC_CR2_EXTSEL_SHIFT) /* 001: Timer 1 CC2 event */
+# define ADC_CR2_EXTSEL_T1CC3 (2 << ADC_CR2_EXTSEL_SHIFT) /* 010: Timer 1 CC3 event */
+# define ADC_CR2_EXTSEL_T2CC2 (3 << ADC_CR2_EXTSEL_SHIFT) /* 011: Timer 2 CC2 event */
+# define ADC_CR2_EXTSEL_T3TRGO (4 << ADC_CR2_EXTSEL_SHIFT) /* 100: Timer 3 TRGO event */
+# define ADC_CR2_EXTSEL_T4CC4 (5 << ADC_CR2_EXTSEL_SHIFT) /* 101: Timer 4 CC4 event */
+# define ADC_CR2_EXTSEL_EXTI11 (6 << ADC_CR2_EXTSEL_SHIFT) /* 110: EXTI line11 */
+# define ADC_CR2_EXTSEL_SWSTART (7 << ADC_CR2_EXTSEL_SHIFT) /* 111: SWSTART */
+
+# define ADC_CR2_EXTTRIG (1 << 20) /* Bit 20: External Trigger Conversion mode for regular channels */
+# define ADC_CR2_JSWSTART (1 << 21) /* Bit 21: Start Conversion of injected channels */
+# define ADC_CR2_SWSTART (1 << 22) /* Bit 22: Start Conversion of regular channels */
+# define ADC_CR2_TSVREFE (1 << 23) /* Bit 23: Temperature Sensor and VREFINT Enable */
+#endif
+
+/* ADC sample time register 1 */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+
+# define ADC_SMPR_3 0 /* 000: 3 cycles */
+# define ADC_SMPR_15 1 /* 001: 15 cycles */
+# define ADC_SMPR_28 2 /* 010: 28 cycles */
+# define ADC_SMPR_56 3 /* 011: 56 cycles */
+# define ADC_SMPR_84 4 /* 100: 84 cycles */
+# define ADC_SMPR_112 5 /* 101: 112 cycles */
+# define ADC_SMPR_144 6 /* 110: 144 cycles */
+# define ADC_SMPR_480 7 /* 111: 480 cycles */
+
+#else
+
+# define ADC_SMPR_1p5 0 /* 000: 1.5 cycles */
+# define ADC_SMPR_7p5 1 /* 001: 7.5 cycles */
+# define ADC_SMPR_13p5 2 /* 010: 13.5 cycles */
+# define ADC_SMPR_28p5 3 /* 011: 28.5 cycles */
+# define ADC_SMPR_41p5 4 /* 100: 41.5 cycles */
+# define ADC_SMPR_55p5 5 /* 101: 55.5 cycles */
+# define ADC_SMPR_71p5 6 /* 110: 71.5 cycles */
+# define ADC_SMPR_239p5 7 /* 111: 239.5 cycles */
+
+#endif
+
+#define ADC_SMPR1_SMP10_SHIFT (0) /* Bits 0-2: Channel 10 Sample time selection */
+#define ADC_SMPR1_SMP10_MASK (7 << ADC_SMPR1_SMP10_SHIFT)
+#define ADC_SMPR1_SMP11_SHIFT (3) /* Bits 3-5: Channel 11 Sample time selection */
+#define ADC_SMPR1_SMP11_MASK (7 << ADC_SMPR1_SMP11_SHIFT)
+#define ADC_SMPR1_SMP12_SHIFT (6) /* Bits 6-8: Channel 12 Sample time selection */
+#define ADC_SMPR1_SMP12_MASK (7 << ADC_SMPR1_SMP12_SHIFT)
+#define ADC_SMPR1_SMP13_SHIFT (9) /* Bits 9-11: Channel 13 Sample time selection */
+#define ADC_SMPR1_SMP13_MASK (7 << ADC_SMPR1_SMP13_SHIFT)
+#define ADC_SMPR1_SMP14_SHIFT (12) /* Bits 12-14: Channel 14 Sample time selection */
+#define ADC_SMPR1_SMP14_MASK (7 << ADC_SMPR1_SMP14_SHIFT)
+#define ADC_SMPR1_SMP15_SHIFT (15) /* Bits 15-17: Channel 15 Sample time selection */
+#define ADC_SMPR1_SMP15_MASK (7 << ADC_SMPR1_SMP15_SHIFT)
+#define ADC_SMPR1_SMP16_SHIFT (18) /* Bits 18-20: Channel 16 Sample time selection */
+#define ADC_SMPR1_SMP16_MASK (7 << ADC_SMPR1_SMP16_SHIFT)
+#define ADC_SMPR1_SMP17_SHIFT (21) /* Bits 21-23: Channel 17 Sample time selection */
+#define ADC_SMPR1_SMP17_MASK (7 << ADC_SMPR1_SMP17_SHIFT)
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define ADC_SMPR1_SMP18_SHIFT (21) /* Bits 24-26: Channel 18 Sample time selection */
+# define ADC_SMPR1_SMP18_MASK (7 << ADC_SMPR1_SMP17_SHIFT)
+#endif
+
+/* ADC sample time register 2 */
+
+#define ADC_SMPR2_SMP0_SHIFT (0) /* Bits 2-0: Channel 0 Sample time selection */
+#define ADC_SMPR2_SMP0_MASK (7 << ADC_SMPR1_SMP0_SHIFT)
+#define ADC_SMPR2_SMP1_SHIFT (3) /* Bits 5-3: Channel 1 Sample time selection */
+#define ADC_SMPR2_SMP1_MASK (7 << ADC_SMPR1_SMP1_SHIFT)
+#define ADC_SMPR2_SMP2_SHIFT (6) /* Bits 8-6: Channel 2 Sample time selection */
+#define ADC_SMPR2_SMP2_MASK (7 << ADC_SMPR1_SMP2_SHIFT)
+#define ADC_SMPR2_SMP3_SHIFT (9) /* Bits 11-9: Channel 3 Sample time selection */
+#define ADC_SMPR2_SMP3_MASK (7 << ADC_SMPR1_SMP3_SHIFT)
+#define ADC_SMPR2_SMP4_SHIFT (12) /* Bits 14-12: Channel 4 Sample time selection */
+#define ADC_SMPR2_SMP4_MASK (7 << ADC_SMPR1_SMP4_SHIFT)
+#define ADC_SMPR2_SMP5_SHIFT (15) /* Bits 17-15: Channel 5 Sample time selection */
+#define ADC_SMPR2_SMP5_MASK (7 << ADC_SMPR1_SMP5_SHIFT)
+#define ADC_SMPR2_SMP6_SHIFT (18) /* Bits 20-18: Channel 6 Sample time selection */
+#define ADC_SMPR2_SMP6_MASK (7 << ADC_SMPR1_SMP6_SHIFT)
+#define ADC_SMPR2_SMP7_SHIFT (21) /* Bits 23-21: Channel 7 Sample time selection */
+#define ADC_SMPR2_SMP7_MASK (7 << ADC_SMPR1_SMP7_SHIFT)
+#define ADC_SMPR2_SMP8_SHIFT (24) /* Bits 26-24: Channel 8 Sample time selection */
+#define ADC_SMPR2_SMP8_MASK (7 << ADC_SMPR1_SMP8_SHIFT)
+#define ADC_SMPR2_SMP9_SHIFT (27) /* Bits 29-27: Channel 9 Sample time selection */
+#define ADC_SMPR2_SMP9_MASK (7 << ADC_SMPR1_SMP9_SHIFT)
+
+/* ADC injected channel data offset register 1-4 */
+
+#define ADC_JOFR_SHIFT (0) /* Bits 11-0: Data offset for injected channel x */
+#define ADC_JOFR_MASK (0x0fff << ADC_JOFR_SHIFT)
+
+/* ADC watchdog high threshold register */
+
+#define ADC_HTR_SHIFT (0) /* Bits 11-0: Analog watchdog high threshold */
+#define ADC_HTR_MASK (0x0fff << ADC_HTR_SHIFT)
+
+/* ADC watchdog low threshold register */
+
+#define ADC_LTR_SHIFT (0) /* Bits 11-0: Analog watchdog low threshold */
+#define ADC_LTR_MASK (0x0fff << ADC_LTR_SHIFT)
+
+/* ADC regular sequence register 1 */
+
+#define ADC_SQR1_SQ13_SHIFT (0) /* Bits 4-0: 13th conversion in regular sequence */
+#define ADC_SQR1_SQ13_MASK (0x1f << ADC_SQR1_SQ13_SHIFT)
+#define ADC_SQR1_SQ14_SHIFT (5) /* Bits 9-5: 14th conversion in regular sequence */
+#define ADC_SQR1_SQ14_MASK (0x1f << ADC_SQR1_SQ14_SHIFT)
+#define ADC_SQR1_SQ15_SHIFT (10) /* Bits 14-10: 15th conversion in regular sequence */
+#define ADC_SQR1_SQ15_MASK (0x1f << ADC_SQR1_SQ15_SHIFT)
+#define ADC_SQR1_SQ16_SHIFT (15) /* Bits 19-15: 16th conversion in regular sequence */
+#define ADC_SQR1_SQ16_MASK (0x1f << ADC_SQR1_SQ16_SHIFT)
+#define ADC_SQR1_L_SHIFT (20) /* Bits 23-20: Regular channel sequence length */
+#define ADC_SQR1_L_MASK (0x0f << ADC_SQR1_L_SHIFT)
+#define ADC_SQR1_RESERVED (0xff000000)
+
+/* ADC regular sequence register 2 */
+
+#define ADC_SQR2_SQ7_SHIFT (0) /* Bits 4-0: 7th conversion in regular sequence */
+#define ADC_SQR2_SQ7_MASK (0x1f << ADC_SQR2_SQ7_SHIFT)
+#define ADC_SQR2_SQ8_SHIFT (5) /* Bits 9-5: 8th conversion in regular sequence */
+#define ADC_SQR2_SQ8_MASK (0x1f << ADC_SQR2_SQ8_SHIFT)
+#define ADC_SQR2_SQ9_SHIFT (10) /* Bits 14-10: 9th conversion in regular sequence */
+#define ADC_SQR2_SQ9_MASK (0x1f << ADC_SQR2_SQ9_SHIFT)
+#define ADC_SQR2_SQ10_SHIFT (15) /* Bits 19-15: 10th conversion in regular sequence */
+#define ADC_SQR2_SQ10_MASK (0x1f << ADC_SQR2_SQ10_SHIFT)
+#define ADC_SQR2_SQ11_SHIFT (20) /* Bits 24-20: 11th conversion in regular sequence */
+#define ADC_SQR2_SQ11_MASK (0x1f << ADC_SQR2_SQ11_SHIFT )
+#define ADC_SQR2_SQ12_SHIFT (25) /* Bits 29-25: 12th conversion in regular sequence */
+#define ADC_SQR2_SQ12_MASK (0x1f << ADC_SQR2_SQ12_SHIFT)
+#define ADC_SQR2_RESERVED (0xc0000000)
+
+/* ADC regular sequence register 3 */
+
+#define ADC_SQR3_SQ1_SHIFT (0) /* Bits 4-0: 1st conversion in regular sequence */
+#define ADC_SQR3_SQ1_MASK (0x1f << ADC_SQR3_SQ1_SHIFT)
+#define ADC_SQR3_SQ2_SHIFT (5) /* Bits 9-5: 2nd conversion in regular sequence */
+#define ADC_SQR3_SQ2_MASK (0x1f << ADC_SQR3_SQ2_SHIFT)
+#define ADC_SQR3_SQ3_SHIFT (10) /* Bits 14-10: 3rd conversion in regular sequence */
+#define ADC_SQR3_SQ3_MASK (0x1f << ADC_SQR3_SQ3_SHIFT)
+#define ADC_SQR3_SQ4_SHIFT (15) /* Bits 19-15: 4th conversion in regular sequence */
+#define ADC_SQR3_SQ4_MASK (0x1f << ADC_SQR3_SQ4_SHIFT)
+#define ADC_SQR3_SQ5_SHIFT (20) /* Bits 24-20: 5th conversion in regular sequence */
+#define ADC_SQR3_SQ5_MASK (0x1f << ADC_SQR3_SQ5_SHIFT )
+#define ADC_SQR3_SQ6_SHIFT (25) /* Bits 29-25: 6th conversion in regular sequence */
+#define ADC_SQR3_SQ6_MASK (0x1f << ADC_SQR3_SQ6_SHIFT)
+#define ADC_SQR3_RESERVED (0xc0000000)
+
+/* ADC injected sequence register */
+
+#define ADC_JSQR_JSQ1_SHIFT (0) /* Bits 4-0: 1st conversion in injected sequence */
+#define ADC_JSQR_JSQ1_MASK (0x1f << ADC_JSQR_JSQ1_SHIFT)
+#define ADC_JSQR_JSQ2_SHIFT (5) /* Bits 9-5: 2nd conversion in injected sequence */
+#define ADC_JSQR_JSQ2_MASK (0x1f << ADC_JSQR_JSQ2_MASK)
+#define ADC_JSQR_JSQ3_SHIFT (10) /* Bits 14-10: 3rd conversion in injected sequence */
+#define ADC_JSQR_JSQ3_MASK (0x1f << ADC_JSQR_JSQ3_SHIFT)
+#define ADC_JSQR_JSQ4_SHIFT (15) /* Bits 19-15: 4th conversion in injected sequence */
+#define ADC_JSQR_JSQ4_MASK (0x1f << ADC_JSQR_JSQ4_SHIFT)
+#define ADC_JSQR_JL_SHIFT (20) /* Bits 21-20: Injected Sequence length */
+#define ADC_JSQR_JL_MASK (3 << ADC_JSQR_JL_SHIFT)
+
+/* ADC injected data register 1-4 */
+
+#define ADC_JDR_SHIFT (0) /* Bits 15-0: Injected data */
+#define ADC_JDR_MASK (0xffff << ADC_JDR_SHIFT)
+
+/* ADC regular data register */
+
+#define ADC_DR_DATA_SHIFT (0) /* Bits 15-0 Regular data */
+#define ADC_DR_DATA_MASK (0xffff << ADC_DR_DATA_SHIFT)
+#define ADC_DR_ADC2DATA_SHIFT (16) /* Bits 31-16: ADC2 data */
+#define ADC_DR_ADC2DATA_MASK (0xffff << ADC_DR_ADC2DATA_SHIFT)
+
+/* Common status register */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define ADC_CSR_AWD1 (1 << 0) /* Bit 0: Analog watchdog flag of ADC1 (copy of AWD in ADC1_SR) */
+# define ADC_CSR_EOC1 (1 << 1) /* Bit 1: End of conversion of ADC1 (copy of EOC in ADC1_SR) */
+# define ADC_CSR_JEOC1 (1 << 2) /* Bit 2: Injected channel end of conversion of ADC1 (copy of JEOC in ADC1_SR) */
+# define ADC_CSR_JSTRT1 (1 << 3) /* Bit 3: Injected channel Start flag of ADC1 (copy of JSTRT in ADC1_SR) */
+# define ADC_CSR_STRT1 (1 << 4) /* Bit 4: Regular channel Start flag of ADC1 (copy of STRT in ADC1_SR) */
+# define ADC_CSR_OVR1 (1 << 5) /* Bit 5: Overrun flag of ADC1 (copy of OVR in ADC1_SR) */
+ /* Bits 6-7: Reserved, must be kept at reset value. */
+# define ADC_CSR_AWD2 (1 << 8) /* Bit 8: Analog watchdog flag of ADC2 (copy of AWD in ADC2_SR) */
+# define ADC_CSR_EOC2 (1 << 9) /* Bit 9: End of conversion of ADC2 (copy of EOC in ADC2_SR) */
+# define ADC_CSR_JEOC2 (1 << 10) /* Bit 10: Injected channel end of conversion of ADC2 (copy of JEOC in ADC2_SR) */
+# define ADC_CSR_JSTRT2 (1 << 11) /* Bit 11: Injected channel Start flag of ADC2 (copy of JSTRT in ADC2_SR) */
+# define ADC_CSR_STRT2 (1 << 12) /* Bit 12: Regular channel Start flag of ADC2 (copy of STRT in ADC2_SR) */
+# define ADC_CSR_OVR2 (1 << 13) /* Bit 13: Overrun flag of ADC2 (copy of OVR in ADC2_SR) */
+ /* Bits 14-15: Reserved, must be kept at reset value. */
+# define ADC_CSR_AWD3 (1 << 16) /* Bit 16: ADC3 Analog watchdog flag (copy of AWD in ADC3_SR) */
+# define ADC_CSR_EOC3 (1 << 17) /* Bit 17: ADC3 End of conversion (copy of EOC in ADC3_SR) */
+# define ADC_CSR_JEOC3 (1 << 18) /* Bit 18: ADC3 Injected channel end of conversion (copy of JEOC in ADC3_SR) */
+# define ADC_CSR_JSTRT3 (1 << 19) /* Bit 19: ADC3 Injected channel Start flag (copy of JSTRT in ADC3_SR) */
+# define ADC_CSR_STRT3 (1 << 20) /* Bit 20: ADC3 Regular channel Start flag (copy of STRT in ADC3_SR). */
+# define ADC_CSR_OVR3 (1 << 21) /* Bit 21: ADC3 overrun flag (copy of OVR in ADC3_SR). */
+ /* Bits 22-31: Reserved, must be kept at reset value. */
+#endif
+
+/* Common control register */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define ADC_CCR_MULTI_SHIFT (0) /* Bits 0-4: Multi ADC mode selection */
+# define ADC_CCR_MULTI_MASK (31 << ADC_CCR_MULTI_SHIFT)
+# define ADC_CCR_MULTI_NONE (0 << ADC_CCR_MULTI_SHIFT) /* 00000: Independent mode */
+ /* 00001 to 01001: Dual mode (ADC1 and ADC2), ADC3 independent */
+# define ADC_CCR_MULTI_RSISM2 (1 << ADC_CCR_MULTI_SHIFT) /* 00001: Combined regular simultaneous + injected simultaneous mode */
+# define ADC_CCR_MULTI_RSATM2 (2 << ADC_CCR_MULTI_SHIFT) /* 00010: Combined regular simultaneous + alternate trigger mode */
+# define ADC_CCR_MULTI_ISM2 (5 << ADC_CCR_MULTI_SHIFT) /* 00101: Injected simultaneous mode only */
+# define ADC_CCR_MULTI_RSM2 (6 << ADC_CCR_MULTI_SHIFT) /* 00110: Regular simultaneous mode only */
+# define ADC_CCR_MULTI_IM2 (7 << ADC_CCR_MULTI_SHIFT) /* 00111: interleaved mode only */
+# define ADC_CCR_MULTI_ATM2 (9 << ADC_CCR_MULTI_SHIFT) /* 01001: Alternate trigger mode only */
+ /* 10001 to 11001: Triple mode (ADC1, 2 and 3) */
+# define ADC_CCR_MULTI_RSISM3 (17 << ADC_CCR_MULTI_SHIFT) /* 10001: Combined regular simultaneous + injected simultaneous mode */
+# define ADC_CCR_MULTI_RSATM3 (18 << ADC_CCR_MULTI_SHIFT) /* 10010: Combined regular simultaneous + alternate trigger mode */
+# define ADC_CCR_MULTI_ISM3 (21 << ADC_CCR_MULTI_SHIFT) /* 10101: Injected simultaneous mode only */
+# define ADC_CCR_MULTI_RSM3 (22 << ADC_CCR_MULTI_SHIFT) /* 10110: Regular simultaneous mode only */
+# define ADC_CCR_MULTI_IM3 (23 << ADC_CCR_MULTI_SHIFT) /* 10111: interleaved mode only */
+# define ADC_CCR_MULTI_ATM3 (25 << ADC_CCR_MULTI_SHIFT) /* 11001: Alternate trigger mode only */
+ /* Bits 5-7: Reserved, must be kept at reset value. */
+# define ADC_CCR_DELAY_SHIFT (8) /* Bits 8-11: Delay between 2 sampling phases */
+# define ADC_CCR_DELAY_MASK (15 << ADC_CCR_DELAY_SHIFT)
+# define ADC_CCR_DELAY(n) (((5)-5) << ADC_CCR_DELAY_SHIFT) /* n * TADCCLK, n=5-20 */
+ /* Bit 12 Reserved, must be kept at reset value. */
+# define ADC_CCR_DDS (1 << 13) /* Bit 13: DMA disable selection (for multi-ADC mode) */
+
+# define ADC_CCR_DMA_SHIFT (14) /* Bits 14-15: Direct memory access mode for multi ADC mode */
+# define ADC_CCR_DMA_MASK (3 << ADC_CCR_DMA_SHIFT)
+# define ADC_CCR_DMA_DISABLED (0 << ADC_CCR_DMA_SHIFT) /* 00: DMA mode disabled */
+# define ADC_CCR_DMA_MODE1 (1 << ADC_CCR_DMA_SHIFT) /* 01: DMA mode 1 enabled */
+# define ADC_CCR_DMA_MODE2 (2 << ADC_CCR_DMA_SHIFT) /* 10: DMA mode 2 enabled */
+# define ADC_CCR_DMA_MODE3 (3 << ADC_CCR_DMA_SHIFT) /* 11: DMA mode 3 enabled */
+
+# define ADC_CCR_ADCPRE_SHIFT (16) /* Bits 16-17: ADC prescaler */
+# define ADC_CCR_ADCPRE_MASK (3 << ADC_CCR_ADCPRE_SHIFT)
+# define ADC_CCR_ADCPRE_DIV2 (0 << ADC_CCR_ADCPRE_SHIFT) /* 00: PCLK2 divided by 2 */
+# define ADC_CCR_ADCPRE_DIV4 (1 << ADC_CCR_ADCPRE_SHIFT) /* 01: PCLK2 divided by 4 */
+# define ADC_CCR_ADCPRE_DIV6 (2 << ADC_CCR_ADCPRE_SHIFT) /* 10: PCLK2 divided by 6 */
+# define ADC_CCR_ADCPRE_DIV8 (3 << ADC_CCR_ADCPRE_SHIFT) /* 11: PCLK2 divided by 8 */
+ /* Bits 18-21: Reserved, must be kept at reset value. */
+# define ADC_CCR_VBATE (1 << 22) /* Bit 22: VBAT enable */
+# define ADC_CCR_TSVREFE (1 << 23) /* Bit 23: Temperature sensor and VREFINT enable */
+ /* Bits 24-31 Reserved, must be kept at reset value. */
+#endif
+
+/* Data register for dual and triple modes (32-bit data with no named fields) */
+
+/****************************************************************************************************
+ * Public Types
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Public Data
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_ADC_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_bkp.h b/nuttx/arch/arm/src/stm32/chip/stm32_bkp.h
new file mode 100644
index 000000000..1788bdee0
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_bkp.h
@@ -0,0 +1,190 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_bkp.h
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_CHIP_STM32_BKP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_BKP_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#if defined(CONFIG_STM32_HIGHDENSITY) || defined(CONFIG_STM32_CONNECTIVITYLINE)
+# define CONFIG_STM32_NBKP_BYTES 84
+# define CONFIG_STM32_NBKP_REGS 42
+#else
+# define CONFIG_STM32_NBKP_BYTES 20
+# define CONFIG_STM32_NBKP_REGS 10
+#endif
+
+/* Register Offsets *****************************************************************/
+
+#if defined(CONFIG_STM32_HIGHDENSITY) || defined(CONFIG_STM32_CONNECTIVITYLINE)
+# define STM32_BKP_DR_OFFSET(n) ((n) > 10 ? 0x0040+4*((n)-10) : 0x0004+4*(n))
+#else
+# define STM32_BKP_DR_OFFSET(n) (0x0004+4*(n))
+#endif
+
+#define STM32_BKP_DR1_OFFSET 0x0004 /* Backup data register 1 */
+#define STM32_BKP_DR2_OFFSET 0x0008 /* Backup data register 2 */
+#define STM32_BKP_DR3_OFFSET 0x000c /* Backup data register 3 */
+#define STM32_BKP_DR4_OFFSET 0x0010 /* Backup data register 4 */
+#define STM32_BKP_DR5_OFFSET 0x0014 /* Backup data register 5 */
+#define STM32_BKP_DR6_OFFSET 0x0018 /* Backup data register 6 */
+#define STM32_BKP_DR7_OFFSET 0x001c /* Backup data register 7 */
+#define STM32_BKP_DR8_OFFSET 0x0020 /* Backup data register 8 */
+#define STM32_BKP_DR9_OFFSET 0x0024 /* Backup data register 9 */
+#define STM32_BKP_DR10_OFFSET 0x0028 /* Backup data register 10 */
+
+#define STM32_BKP_RTCCR_OFFSET 0x002c /* RTC clock calibration register */
+#define STM32_BKP_CR_OFFSET 0x0030 /* Backup control register */
+#define STM32_BKP_CSR_OFFSET 0x0034 /* Backup control/status register */
+
+#if defined(CONFIG_STM32_HIGHDENSITY) || defined(CONFIG_STM32_CONNECTIVITYLINE)
+# define STM32_BKP_DR11_OFFSET 0x0040 /* Backup data register 11 */
+# define STM32_BKP_DR12_OFFSET 0x0044 /* Backup data register 12 */
+# define STM32_BKP_DR13_OFFSET 0x0048 /* Backup data register 13 */
+# define STM32_BKP_DR14_OFFSET 0x004c /* Backup data register 14 */
+# define STM32_BKP_DR15_OFFSET 0x0050 /* Backup data register 15 */
+# define STM32_BKP_DR16_OFFSET 0x0054 /* Backup data register 16 */
+# define STM32_BKP_DR17_OFFSET 0x0058 /* Backup data register 17 */
+# define STM32_BKP_DR18_OFFSET 0x005c /* Backup data register 18 */
+# define STM32_BKP_DR19_OFFSET 0x0060 /* Backup data register 19 */
+# define STM32_BKP_DR20_OFFSET 0x0064 /* Backup data register 20 */
+# define STM32_BKP_DR21_OFFSET 0x0068 /* Backup data register 21 */
+# define STM32_BKP_DR22_OFFSET 0x006c /* Backup data register 22 */
+# define STM32_BKP_DR23_OFFSET 0x0070 /* Backup data register 23 */
+# define STM32_BKP_DR24_OFFSET 0x0074 /* Backup data register 24 */
+# define STM32_BKP_DR25_OFFSET 0x0078 /* Backup data register 25 */
+# define STM32_BKP_DR26_OFFSET 0x007c /* Backup data register 26 */
+# define STM32_BKP_DR27_OFFSET 0x0080 /* Backup data register 27 */
+# define STM32_BKP_DR28_OFFSET 0x0084 /* Backup data register 28 */
+# define STM32_BKP_DR29_OFFSET 0x0088 /* Backup data register 29 */
+# define STM32_BKP_DR30_OFFSET 0x008c /* Backup data register 30 */
+# define STM32_BKP_DR31_OFFSET 0x0090 /* Backup data register 31 */
+# define STM32_BKP_DR32_OFFSET 0x0094 /* Backup data register 32 */
+# define STM32_BKP_DR33_OFFSET 0x0098 /* Backup data register 33 */
+# define STM32_BKP_DR34_OFFSET 0x009c /* Backup data register 34 */
+# define STM32_BKP_DR35_OFFSET 0x00a0 /* Backup data register 35 */
+# define STM32_BKP_DR36_OFFSET 0x00a4 /* Backup data register 36 */
+# define STM32_BKP_DR37_OFFSET 0x00a8 /* Backup data register 37 */
+# define STM32_BKP_DR38_OFFSET 0x00ac /* Backup data register 38 */
+# define STM32_BKP_DR39_OFFSET 0x00b0 /* Backup data register 39 */
+# define STM32_BKP_DR40_OFFSET 0x00b4 /* Backup data register 40 */
+# define STM32_BKP_DR41_OFFSET 0x00b8 /* Backup data register 41 */
+# define STM32_BKP_DR42_OFFSET 0x00bc /* Backup data register 42 */
+#endif
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_BKP_RTCCR (STM32_BKP_BASE+STM32_BKP_RTCCR_OFFSET)
+#define STM32_BKP_CR (STM32_BKP_BASE+STM32_BKP_CR_OFFSET)
+#define STM32_BKP_CSR (STM32_BKP_BASE+STM32_BKP_CSR_OFFSET)
+
+#define STM32_BKP_DR(n) (STM32_BKP_BASE+STM32_BKP_DR_OFFSET(n))
+#define STM32_BKP_DR1 (STM32_BKP_BASE+STM32_BKP_DR1_OFFSET)
+#define STM32_BKP_DR2 (STM32_BKP_BASE+STM32_BKP_DR2_OFFSET)
+#define STM32_BKP_DR3 (STM32_BKP_BASE+STM32_BKP_DR3_OFFSET)
+#define STM32_BKP_DR4 (STM32_BKP_BASE+STM32_BKP_DR4_OFFSET)
+#define STM32_BKP_DR5 (STM32_BKP_BASE+STM32_BKP_DR5_OFFSET)
+#define STM32_BKP_DR6 (STM32_BKP_BASE+STM32_BKP_DR6_OFFSET)
+#define STM32_BKP_DR7 (STM32_BKP_BASE+STM32_BKP_DR7_OFFSET)
+#define STM32_BKP_DR8 (STM32_BKP_BASE+STM32_BKP_DR8_OFFSET)
+#define STM32_BKP_DR9 (STM32_BKP_BASE+STM32_BKP_DR9_OFFSET)
+#define STM32_BKP_DR10 (STM32_BKP_BASE+STM32_BKP_DR10_OFFSET)
+
+#if defined(CONFIG_STM32_HIGHDENSITY) || defined(CONFIG_STM32_CONNECTIVITYLINE)
+# define STM32_BKP_DR11 (STM32_BKP_BASE+STM32_BKP_DR11_OFFSET)
+# define STM32_BKP_DR12 (STM32_BKP_BASE+STM32_BKP_DR12_OFFSET)
+# define STM32_BKP_DR13 (STM32_BKP_BASE+STM32_BKP_DR13_OFFSET)
+# define STM32_BKP_DR14 (STM32_BKP_BASE+STM32_BKP_DR14_OFFSET)
+# define STM32_BKP_DR15 (STM32_BKP_BASE+STM32_BKP_DR15_OFFSET)
+# define STM32_BKP_DR16 (STM32_BKP_BASE+STM32_BKP_DR16_OFFSET)
+# define STM32_BKP_DR17 (STM32_BKP_BASE+STM32_BKP_DR17_OFFSET)
+# define STM32_BKP_DR18 (STM32_BKP_BASE+STM32_BKP_DR18_OFFSET)
+# define STM32_BKP_DR19 (STM32_BKP_BASE+STM32_BKP_DR19_OFFSET)
+# define STM32_BKP_DR20 (STM32_BKP_BASE+STM32_BKP_DR20_OFFSET)
+# define STM32_BKP_DR21 (STM32_BKP_BASE+STM32_BKP_DR21_OFFSET)
+# define STM32_BKP_DR22 (STM32_BKP_BASE+STM32_BKP_DR22_OFFSET)
+# define STM32_BKP_DR23 (STM32_BKP_BASE+STM32_BKP_DR23_OFFSET)
+# define STM32_BKP_DR24 (STM32_BKP_BASE+STM32_BKP_DR24_OFFSET)
+# define STM32_BKP_DR25 (STM32_BKP_BASE+STM32_BKP_DR25_OFFSET)
+# define STM32_BKP_DR26 (STM32_BKP_BASE+STM32_BKP_DR26_OFFSET)
+# define STM32_BKP_DR27 (STM32_BKP_BASE+STM32_BKP_DR27_OFFSET)
+# define STM32_BKP_DR28 (STM32_BKP_BASE+STM32_BKP_DR28_OFFSET)
+# define STM32_BKP_DR29 (STM32_BKP_BASE+STM32_BKP_DR29_OFFSET)
+# define STM32_BKP_DR30 (STM32_BKP_BASE+STM32_BKP_DR30_OFFSET)
+# define STM32_BKP_DR31 (STM32_BKP_BASE+STM32_BKP_DR31_OFFSET)
+# define STM32_BKP_DR32 (STM32_BKP_BASE+STM32_BKP_DR32_OFFSET)
+# define STM32_BKP_DR33 (STM32_BKP_BASE+STM32_BKP_DR33_OFFSET)
+# define STM32_BKP_DR34 (STM32_BKP_BASE+STM32_BKP_DR34_OFFSET)
+# define STM32_BKP_DR35 (STM32_BKP_BASE+STM32_BKP_DR35_OFFSET)
+# define STM32_BKP_DR36 (STM32_BKP_BASE+STM32_BKP_DR36_OFFSET)
+# define STM32_BKP_DR37 (STM32_BKP_BASE+STM32_BKP_DR37_OFFSET)
+# define STM32_BKP_DR38 (STM32_BKP_BASE+STM32_BKP_DR38_OFFSET)
+# define STM32_BKP_DR39 (STM32_BKP_BASE+STM32_BKP_DR39_OFFSET)
+# define STM32_BKP_DR40 (STM32_BKP_BASE+STM32_BKP_DR40_OFFSET)
+# define STM32_BKP_DR41 (STM32_BKP_BASE+STM32_BKP_DR41_OFFSET)
+# define STM32_BKP_DR42 (STM32_BKP_BASE+STM32_BKP_DR42_OFFSET)
+#endif
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* RTC clock calibration register */
+
+#define BKP_RTCCR_CAL_SHIFT (0) /* Bits 6-0: Calibration value */
+#define BKP_RTCCR_CAL_MASK (0x7f << BKP_RTCCR_CAL_SHIFT)
+#define BKP_RTCCR_CCO (1 << 7) /* Bit 7: Calibration Clock Output */
+#define BKP_RTCCR_ASOE (1 << 8) /* Bit 8: Alarm or Second Output Enable */
+#define BKP_RTCCR_ASOS (1 << 9) /* Bit 9: Alarm or Second Output Selection */
+
+/* Backup control register */
+
+#define BKP_CR_TPE (1 << 0) /* Bit 0: TAMPER pin enable */
+#define BKP_CR_TPAL (1 << 1) /* Bit 1: TAMPER pin active level */
+
+/* Backup control/status register */
+
+#define BKP_CSR_CTE (1 << 0) /* Bit 0: Clear Tamper event */
+#define BKP_CSR_CTI (1 << 1) /* Bit 1: Clear Tamper Interrupt */
+#define BKP_CSR_TPIE (1 << 2) /* Bit 2: TAMPER Pin interrupt enable */
+#define BKP_CSR_TEF (1 << 8) /* Bit 8: Tamper Event Flag */
+#define BKP_CSR_TIF (1 << 9) /* Bit 9: Tamper Interrupt Flag */
+
+/* Backup data register */
+
+#define BKP_DR_SHIFT (0) /* Bits 1510: Backup data */
+#define BKP_DR_MASK (0xffff << BKP_DR_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_BKP_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_can.h b/nuttx/arch/arm/src/stm32/chip/stm32_can.h
new file mode 100644
index 000000000..253bf68fc
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_can.h
@@ -0,0 +1,505 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_can.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_CHIP_STM32_CAN_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_CAN_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* 3 TX mailboxes */
+
+#define CAN_TXMBOX1 0
+#define CAN_TXMBOX2 1
+#define CAN_TXMBOX3 2
+
+/* 2 RX mailboxes */
+
+#define CAN_RXMBOX1 0
+#define CAN_RXMBOX2 1
+
+/* Number of filters depends on silicon */
+
+#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define CAN_NFILTERS 28
+#else
+# define CAN_NFILTERS 14
+#endif
+
+/* Register Offsets *****************************************************************/
+
+/* CAN control and status registers */
+
+#define STM32_CAN_MCR_OFFSET 0x0000 /* CAN master control register */
+#define STM32_CAN_MSR_OFFSET 0x0004 /* CAN master status register */
+#define STM32_CAN_TSR_OFFSET 0x0008 /* CAN transmit status register */
+#define STM32_CAN_RF0R_OFFSET 0x000c /* CAN receive FIFO 0 register */
+#define STM32_CAN_RF1R_OFFSET 0x0010 /* CAN receive FIFO 1 register */
+#define STM32_CAN_IER_OFFSET 0x0014 /* CAN interrupt enable register */
+#define STM32_CAN_ESR_OFFSET 0x0018 /* CAN error status register */
+#define STM32_CAN_BTR_OFFSET 0x001c /* CAN bit timing register */
+
+/* CAN mailbox registers (3 TX and 2 RX) */
+
+#define STM32_CAN_TIR_OFFSET(m) (0x0180+((m)<<4))
+#define STM32_CAN_TI0R_OFFSET 0x0180 /* TX mailbox identifier register 0 */
+#define STM32_CAN_TI1R_OFFSET 0x0190 /* TX mailbox identifier register 1 */
+#define STM32_CAN_TI2R_OFFSET 0x01a0 /* TX mailbox identifier register 2 */
+
+#define STM32_CAN_TDTR_OFFSET(m) (0x0184+((m)<<4))
+#define STM32_CAN_TDT0R_OFFSET 0x0184 /* Mailbox data length control and time stamp register 0 */
+#define STM32_CAN_TDT1R_OFFSET 0x0194 /* Mailbox data length control and time stamp register 1 */
+#define STM32_CAN_TDT2R_OFFSET 0x01a4 /* Mailbox data length control and time stamp register 2 */
+
+#define STM32_CAN_TDLR_OFFSET(m) (0x0188+((m)<<4))
+#define STM32_CAN_TDL0R_OFFSET 0x0188 /* Mailbox data low register 0 */
+#define STM32_CAN_TDL1R_OFFSET 0x0198 /* Mailbox data low register 1 */
+#define STM32_CAN_TDL2R_OFFSET 0x01a8 /* Mailbox data low register 2 */
+
+#define STM32_CAN_TDHR_OFFSET(m) (0x018c+((m)<<4))
+#define STM32_CAN_TDH0R_OFFSET 0x018c /* Mailbox data high register 0 */
+#define STM32_CAN_TDH1R_OFFSET 0x019c /* Mailbox data high register 1 */
+#define STM32_CAN_TDH2R_OFFSET 0x01ac /* Mailbox data high register 2 */
+
+#define STM32_CAN_RIR_OFFSET(m) (0x01b0+((m)<<4))
+#define STM32_CAN_RI0R_OFFSET 0x01b0 /* Rx FIFO mailbox identifier register 0 */
+#define STM32_CAN_RI1R_OFFSET 0x01c0 /* Rx FIFO mailbox identifier register 1 */
+
+#define STM32_CAN_RDTR_OFFSET(m) (0x01b4+((m)<<4))
+#define STM32_CAN_RDT0R_OFFSET 0x01b4 /* Rx FIFO mailbox data length control and time stamp register 0 */
+#define STM32_CAN_RDT1R_OFFSET 0x01c4 /* Rx FIFO mailbox data length control and time stamp register 1 */
+
+#define STM32_CAN_RDLR_OFFSET(m) (0x01b8+((m)<<4))
+#define STM32_CAN_RDL0R_OFFSET 0x01b8 /* Receive FIFO mailbox data low register 0 */
+#define STM32_CAN_RDL1R_OFFSET 0x01c8 /* Receive FIFO mailbox data low register 1 */
+
+#define STM32_CAN_RDHR_OFFSET(m) (0x01bc+((m)<<4))
+#define STM32_CAN_RDH0R_OFFSET 0x01bc /* Receive FIFO mailbox data high register 0 */
+#define STM32_CAN_RDH1R_OFFSET 0x01cc /* Receive FIFO mailbox data high register 1 */
+
+/* CAN filter registers */
+
+#define STM32_CAN_FMR_OFFSET 0x0200 /* CAN filter master register */
+#define STM32_CAN_FM1R_OFFSET 0x0204 /* CAN filter mode register */
+#define STM32_CAN_FS1R_OFFSET 0x020c /* CAN filter scale register */
+#define STM32_CAN_FFA1R_OFFSET 0x0214 /* CAN filter FIFO assignment register */
+#define STM32_CAN_FA1R_OFFSET 0x021c /* CAN filter activation register */
+
+/* There are 14 or 28 filter banks (depending) on the device. Each filter bank is
+ * composed of two 32-bit registers, CAN_FiR:
+ * F0R1 Offset 0x240
+ * F0R2 Offset 0x244
+ * F1R1 Offset 0x248
+ * F1R2 Offset 0x24c
+ * ...
+ */
+
+#define STM32_CAN_FR_OFFSET(f,i) (0x240+((f)<<3)+(((i)-1)<<2))
+
+/* Register Addresses ***************************************************************/
+
+#if STM32_NCAN > 0
+# define STM32_CAN1_MCR (STM32_CAN1_BASE+STM32_CAN_MCR_OFFSET)
+# define STM32_CAN1_MSR (STM32_CAN1_BASE+STM32_CAN_MSR_OFFSET)
+# define STM32_CAN1_TSR (STM32_CAN1_BASE+STM32_CAN_TSR_OFFSET)
+# define STM32_CAN1_RF0R (STM32_CAN1_BASE+STM32_CAN_RF0R_OFFSET)
+# define STM32_CAN1_RF1R (STM32_CAN1_BASE+STM32_CAN_RF1R_OFFSET)
+# define STM32_CAN1_IER (STM32_CAN1_BASE+STM32_CAN_IER_OFFSET)
+# define STM32_CAN1_ESR (STM32_CAN1_BASE+STM32_CAN_ESR_OFFSET)
+# define STM32_CAN1_BTR (STM32_CAN1_BASE+STM32_CAN_BTR_OFFSET)
+
+# define STM32_CAN1_TIR(m) (STM32_CAN1_BASE+STM32_CAN_TIR_OFFSET(m))
+# define STM32_CAN1_TI0R (STM32_CAN1_BASE+STM32_CAN_TI0R_OFFSET)
+# define STM32_CAN1_TI1R (STM32_CAN1_BASE+STM32_CAN_TI1R_OFFSET)
+# define STM32_CAN1_TI2R (STM32_CAN1_BASE+STM32_CAN_TI2R_OFFSET)
+
+# define STM32_CAN1_TDTR(m) (STM32_CAN1_BASE+STM32_CAN_TDTR_OFFSET(m))
+# define STM32_CAN1_TDT0R (STM32_CAN1_BASE+STM32_CAN_TDT0R_OFFSET)
+# define STM32_CAN1_TDT1R (STM32_CAN1_BASE+STM32_CAN_TDT1R_OFFSET)
+# define STM32_CAN1_TDT2R (STM32_CAN1_BASE+STM32_CAN_TDT2R_OFFSET)
+
+# define STM32_CAN1_TDLR(m) (STM32_CAN1_BASE+STM32_CAN_TDLR_OFFSET(m))
+# define STM32_CAN1_TDL0R (STM32_CAN1_BASE+STM32_CAN_TDL0R_OFFSET)
+# define STM32_CAN1_TDL1R (STM32_CAN1_BASE+STM32_CAN_TDL1R_OFFSET)
+# define STM32_CAN1_TDL2R (STM32_CAN1_BASE+STM32_CAN_TDL2R_OFFSET)
+
+# define STM32_CAN1_TDHR(m) (STM32_CAN1_BASE+STM32_CAN_TDHR_OFFSET(m))
+# define STM32_CAN1_TDH0R (STM32_CAN1_BASE+STM32_CAN_TDH0R_OFFSET)
+# define STM32_CAN1_TDH1R (STM32_CAN1_BASE+STM32_CAN_TDH1R_OFFSET)
+# define STM32_CAN1_TDH2R (STM32_CAN1_BASE+STM32_CAN_TDH2R_OFFSET)
+
+# define STM32_CAN1_RIR(m) (STM32_CAN1_BASE+STM32_CAN_RIR_OFFSET(m))
+# define STM32_CAN1_RI0R (STM32_CAN1_BASE+STM32_CAN_RI0R_OFFSET)
+# define STM32_CAN1_RI1R (STM32_CAN1_BASE+STM32_CAN_RI1R_OFFSET)
+
+# define STM32_CAN1_RDTR(m) (STM32_CAN1_BASE+STM32_CAN_RDTR_OFFSET(m))
+# define STM32_CAN1_RDT0R (STM32_CAN1_BASE+STM32_CAN_RDT0R_OFFSET)
+# define STM32_CAN1_RDT1R (STM32_CAN1_BASE+STM32_CAN_RDT1R_OFFSET)
+
+# define STM32_CAN1_RDLR(m) (STM32_CAN1_BASE+STM32_CAN_RDLR_OFFSET(m))
+# define STM32_CAN1_RDL0R (STM32_CAN1_BASE+STM32_CAN_RDL0R_OFFSET)
+# define STM32_CAN1_RDL1R (STM32_CAN1_BASE+STM32_CAN_RDL1R_OFFSET)
+
+# define STM32_CAN1_RDHR(m) (STM32_CAN1_BASE+STM32_CAN_RDHR_OFFSET(m))
+# define STM32_CAN1_RDH0R (STM32_CAN1_BASE+STM32_CAN_RDH0R_OFFSET)
+# define STM32_CAN1_RDH1R (STM32_CAN1_BASE+STM32_CAN_RDH1R_OFFSET)
+
+# define STM32_CAN1_FMR (STM32_CAN1_BASE+STM32_CAN_FMR_OFFSET)
+# define STM32_CAN1_FM1R (STM32_CAN1_BASE+STM32_CAN_FM1R_OFFSET)
+# define STM32_CAN1_FS1R (STM32_CAN1_BASE+STM32_CAN_FS1R_OFFSET)
+# define STM32_CAN1_FFA1R (STM32_CAN1_BASE+STM32_CAN_FFA1R_OFFSET)
+# define STM32_CAN1_FA1R (STM32_CAN1_BASE+STM32_CAN_FA1R_OFFSET)
+# define STM32_CAN1_FIR(b,i) (STM32_CAN1_BASE+STM32_CAN_FIR_OFFSET(b,i))
+#endif
+
+#if STM32_NCAN > 1
+# define STM32_CAN2_MCR (STM32_CAN2_BASE+STM32_CAN_MCR_OFFSET)
+# define STM32_CAN2_MSR (STM32_CAN2_BASE+STM32_CAN_MSR_OFFSET)
+# define STM32_CAN2_TSR (STM32_CAN2_BASE+STM32_CAN_TSR_OFFSET)
+# define STM32_CAN2_RF0R (STM32_CAN2_BASE+STM32_CAN_RF0R_OFFSET)
+# define STM32_CAN2_RF1R (STM32_CAN2_BASE+STM32_CAN_RF1R_OFFSET)
+# define STM32_CAN2_IER (STM32_CAN2_BASE+STM32_CAN_IER_OFFSET)
+# define STM32_CAN2_ESR (STM32_CAN2_BASE+STM32_CAN_ESR_OFFSET)
+# define STM32_CAN2_BTR (STM32_CAN2_BASE+STM32_CAN_BTR_OFFSET)
+
+# define STM32_CAN2_TIR(m) (STM32_CAN2_BASE+STM32_CAN_TIR_OFFSET(m))
+# define STM32_CAN2_TI0R (STM32_CAN2_BASE+STM32_CAN_TI0R_OFFSET)
+# define STM32_CAN2_TI1R (STM32_CAN2_BASE+STM32_CAN_TI1R_OFFSET)
+# define STM32_CAN2_TI2R (STM32_CAN2_BASE+STM32_CAN_TI2R_OFFSET)
+
+# define STM32_CAN2_TDTR(m) (STM32_CAN2_BASE+STM32_CAN_TDTR_OFFSET(m))
+# define STM32_CAN2_TDT0R (STM32_CAN2_BASE+STM32_CAN_TDT0R_OFFSET)
+# define STM32_CAN2_TDT1R (STM32_CAN2_BASE+STM32_CAN_TDT1R_OFFSET)
+# define STM32_CAN2_TDT2R (STM32_CAN2_BASE+STM32_CAN_TDT2R_OFFSET)
+
+# define STM32_CAN2_TDLR(m) (STM32_CAN2_BASE+STM32_CAN_TDLR_OFFSET(m))
+# define STM32_CAN2_TDL0R (STM32_CAN2_BASE+STM32_CAN_TDL0R_OFFSET)
+# define STM32_CAN2_TDL1R (STM32_CAN2_BASE+STM32_CAN_TDL1R_OFFSET)
+# define STM32_CAN2_TDL2R (STM32_CAN2_BASE+STM32_CAN_TDL2R_OFFSET)
+
+# define STM32_CAN2_TDHR(m) (STM32_CAN2_BASE+STM32_CAN_TDHR_OFFSET(m))
+# define STM32_CAN2_TDH0R (STM32_CAN2_BASE+STM32_CAN_TDH0R_OFFSET)
+# define STM32_CAN2_TDH1R (STM32_CAN2_BASE+STM32_CAN_TDH1R_OFFSET)
+# define STM32_CAN2_TDH2R (STM32_CAN2_BASE+STM32_CAN_TDH2R_OFFSET)
+
+# define STM32_CAN2_RIR(m) (STM32_CAN2_BASE+STM32_CAN_RIR_OFFSET(m))
+# define STM32_CAN2_RI0R (STM32_CAN2_BASE+STM32_CAN_RI0R_OFFSET)
+# define STM32_CAN2_RI1R (STM32_CAN2_BASE+STM32_CAN_RI1R_OFFSET)
+
+# define STM32_CAN2_RDTR(m) (STM32_CAN2_BASE+STM32_CAN_RDTR_OFFSET(m))
+# define STM32_CAN2_RDT0R (STM32_CAN2_BASE+STM32_CAN_RDT0R_OFFSET)
+# define STM32_CAN2_RDT1R (STM32_CAN2_BASE+STM32_CAN_RDT1R_OFFSET)
+
+# define STM32_CAN2_RDLR(m) (STM32_CAN2_BASE+STM32_CAN_RDLR_OFFSET(m))
+# define STM32_CAN2_RDL0R (STM32_CAN2_BASE+STM32_CAN_RDL0R_OFFSET)
+# define STM32_CAN2_RDL1R (STM32_CAN2_BASE+STM32_CAN_RDL1R_OFFSET)
+
+# define STM32_CAN2_RDHR(m) (STM32_CAN2_BASE+STM32_CAN_RDHR_OFFSET(m))
+# define STM32_CAN2_RDH0R (STM32_CAN2_BASE+STM32_CAN_RDH0R_OFFSET)
+# define STM32_CAN2_RDH1R (STM32_CAN2_BASE+STM32_CAN_RDH1R_OFFSET)
+
+# define STM32_CAN2_FMR (STM32_CAN2_BASE+STM32_CAN_FMR_OFFSET)
+# define STM32_CAN2_FM1R (STM32_CAN2_BASE+STM32_CAN_FM1R_OFFSET)
+# define STM32_CAN2_FS1R (STM32_CAN2_BASE+STM32_CAN_FS1R_OFFSET)
+# define STM32_CAN2_FFA1R (STM32_CAN2_BASE+STM32_CAN_FFA1R_OFFSET)
+# define STM32_CAN2_FA1R (STM32_CAN2_BASE+STM32_CAN_FA1R_OFFSET)
+# define STM32_CAN2_FIR(b,i) (STM32_CAN2_BASE+STM32_CAN_FIR_OFFSET(b,i))
+#endif
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* CAN master control register */
+
+#define CAN_MCR_INRQ (1 << 0) /* Bit 0: Initialization Request */
+#define CAN_MCR_SLEEP (1 << 1) /* Bit 1: Sleep Mode Request */
+#define CAN_MCR_TXFP (1 << 2) /* Bit 2: Transmit FIFO Priority */
+#define CAN_MCR_RFLM (1 << 3) /* Bit 3: Receive FIFO Locked Mode */
+#define CAN_MCR_NART (1 << 4) /* Bit 4: No Automatic Retransmission */
+#define CAN_MCR_AWUM (1 << 5) /* Bit 5: Automatic Wakeup Mode */
+#define CAN_MCR_ABOM (1 << 6) /* Bit 6: Automatic Bus-Off Management */
+#define CAN_MCR_TTCM (1 << 7) /* Bit 7: Time Triggered Communication Mode Enable */
+#define CAN_MCR_RESET (1 << 15) /* Bit 15: bxCAN software master reset */
+#define CAN_MCR_DBF (1 << 16) /* Bit 16: Debug freeze */
+
+/* CAN master status register */
+
+#define CAN_MSR_INAK (1 << 0) /* Bit 0: Initialization Acknowledge */
+#define CAN_MSR_SLAK (1 << 1) /* Bit 1: Sleep Acknowledge */
+#define CAN_MSR_ERRI (1 << 2) /* Bit 2: Error Interrupt */
+#define CAN_MSR_WKUI (1 << 3) /* Bit 3: Wakeup Interrupt */
+#define CAN_MSR_SLAKI (1 << 4) /* Bit 4: Sleep acknowledge interrupt */
+#define CAN_MSR_TXM (1 << 8) /* Bit 8: Transmit Mode */
+#define CAN_MSR_RXM (1 << 9) /* Bit 9: Receive Mode */
+#define CAN_MSR_SAMP (1 << 20) /* Bit 10: Last Sample Point */
+#define CAN_MSR_RX (1 << 11) /* Bit 11: CAN Rx Signal */
+
+/* CAN transmit status register */
+
+#define CAN_TSR_RQCP0 (1 << 0) /* Bit 0: Request Completed Mailbox 0 */
+#define CAN_TSR_TXOK0 (1 << 1) /* Bit 1 : Transmission OK of Mailbox 0 */
+#define CAN_TSR_ALST0 (1 << 2) /* Bit 2 : Arbitration Lost for Mailbox 0 */
+#define CAN_TSR_TERR0 (1 << 3) /* Bit 3 : Transmission Error of Mailbox 0 */
+#define CAN_TSR_ABRQ0 (1 << 7) /* Bit 7 : Abort Request for Mailbox 0 */
+#define CAN_TSR_RQCP1 (1 << 8) /* Bit 8 : Request Completed Mailbox 1 */
+#define CAN_TSR_TXOK1 (1 << 9) /* Bit 9 : Transmission OK of Mailbox 1 */
+#define CAN_TSR_ALST1 (1 << 10) /* Bit 10 : Arbitration Lost for Mailbox 1 */
+#define CAN_TSR_TERR1 (1 << 11) /* Bit 11 : Transmission Error of Mailbox 1 */
+#define CAN_TSR_ABRQ1 (1 << 15) /* Bit 15 : Abort Request for Mailbox 1 */
+#define CAN_TSR_RQCP2 (1 << 16) /* Bit 16 : Request Completed Mailbox 2 */
+#define CAN_TSR_TXOK2 (1 << 17) /* Bit 17 : Transmission OK of Mailbox 2 */
+#define CAN_TSR_ALST2 (1 << 18) /* Bit 18: Arbitration Lost for Mailbox 2 */
+#define CAN_TSR_TERR2 (1 << 19) /* Bit 19: Transmission Error of Mailbox 2 */
+#define CAN_TSR_ABRQ2 (1 << 23) /* Bit 23: Abort Request for Mailbox 2 */
+#define CAN_TSR_CODE_SHIFT (24) /* Bits 25-24: Mailbox Code */
+#define CAN_TSR_CODE_MASK (3 << CAN_TSR_CODE_SHIFT)
+#define CAN_TSR_TME0 (1 << 26) /* Bit 26: Transmit Mailbox 0 Empty */
+#define CAN_TSR_TME1 (1 << 27) /* Bit 27: Transmit Mailbox 1 Empty */
+#define CAN_TSR_TME2 (1 << 28) /* Bit 28: Transmit Mailbox 2 Empty */
+#define CAN_TSR_LOW0 (1 << 29) /* Bit 29: Lowest Priority Flag for Mailbox 0 */
+#define CAN_TSR_LOW1 (1 << 30) /* Bit 30: Lowest Priority Flag for Mailbox 1 */
+#define CAN_TSR_LOW2 (1 << 31) /* Bit 31: Lowest Priority Flag for Mailbox 2 */
+
+/* CAN receive FIFO 0/1 registers */
+
+#define CAN_RFR_FMP_SHIFT (0) /* Bits 1-0: FIFO Message Pending */
+#define CAN_RFR_FMP_MASK (3 << CAN_RFR_FMP_SHIFT)
+#define CAN_RFR_FULL (1 << 3) /* Bit 3: FIFO 0 Full */
+#define CAN_RFR_FOVR (1 << 4) /* Bit 4: FIFO 0 Overrun */
+#define CAN_RFR_RFOM (1 << 5) /* Bit 5: Release FIFO 0 Output Mailbox */
+
+/* CAN interrupt enable register */
+
+#define CAN_IER_TMEIE (1 << 0) /* Bit 0: Transmit Mailbox Empty Interrupt Enable */
+#define CAN_IER_FMPIE0 (1 << 1) /* Bit 1: FIFO Message Pending Interrupt Enable */
+#define CAN_IER_FFIE0 (1 << 2) /* Bit 2: FIFO Full Interrupt Enable */
+#define CAN_IER_FOVIE0 (1 << 3) /* Bit 3: FIFO Overrun Interrupt Enable */
+#define CAN_IER_FMPIE1 (1 << 4) /* Bit 4: FIFO Message Pending Interrupt Enable */
+#define CAN_IER_FFIE1 (1 << 5) /* Bit 5: FIFO Full Interrupt Enable */
+#define CAN_IER_FOVIE1 (1 << 6) /* Bit 6: FIFO Overrun Interrupt Enable */
+#define CAN_IER_EWGIE (1 << 8) /* Bit 8: Error Warning Interrupt Enable */
+#define CAN_IER_EPVIE (1 << 9) /* Bit 9: Error Passive Interrupt Enable */
+#define CAN_IER_BOFIE (1 << 10) /* Bit 10: Bus-Off Interrupt Enable */
+#define CAN_IER_LECIE (1 << 11) /* Bit 11: Last Error Code Interrupt Enable */
+#define CAN_IER_ERRIE (1 << 15) /* Bit 15: Error Interrupt Enable */
+#define CAN_IER_WKUIE (1 << 16) /* Bit 16: Wakeup Interrupt Enable */
+#define CAN_IER_SLKIE (1 << 17) /* Bit 17: Sleep Interrupt Enable */
+
+/* CAN error status register */
+
+#define CAN_ESR_EWGF (1 << 0) /* Bit 0: Error Warning Flag */
+#define CAN_ESR_EPVF (1 << 1) /* Bit 1: Error Passive Flag */
+#define CAN_ESR_BOFF (1 << 2) /* Bit 2: Bus-Off Flag */
+#define CAN_ESR_LEC_SHIFT (4) /* Bits 6-4: Last Error Code */
+#define CAN_ESR_LEC_MASK (7 << CAN_ESR_LEC_SHIFT)
+# define CAN_ESR_NOERROR (0 << CAN_ESR_LEC_SHIFT) /* 000: No Error */
+# define CAN_ESR_STUFFERROR (1 << CAN_ESR_LEC_SHIFT) /* 001: Stuff Error */
+# define CAN_ESR_FORMERROR (2 << CAN_ESR_LEC_SHIFT) /* 010: Form Error */
+# define CAN_ESR_ACKERROR (3 << CAN_ESR_LEC_SHIFT) /* 011: Acknowledgment Error */
+# define CAN_ESR_BRECERROR (4 << CAN_ESR_LEC_SHIFT) /* 100: Bit recessive Error */
+# define CAN_ESR_BDOMERROR (5 << CAN_ESR_LEC_SHIFT) /* 101: Bit dominant Error */
+# define CAN_ESR_CRCERRPR (6 << CAN_ESR_LEC_SHIFT) /* 110: CRC Error */
+# define CAN_ESR_SWERROR (7 << CAN_ESR_LEC_SHIFT) /* 111: Set by software */
+#define CAN_ESR_TEC_SHIFT (16) /* Bits 23-16: LS byte of the 9-bit Transmit Error Counter */
+#define CAN_ESR_TEC_MASK (0xff << CAN_ESR_TEC_SHIF)
+#define CAN_ESR_REC_SHIFT (24) /* Bits 31-24: Receive Error Counter */
+#define CAN_ESR_REC_MASK (0xff << CAN_ESR_REC_SHIFT)
+
+/* CAN bit timing register */
+
+#define CAN_BTR_BRP_SHIFT (0) /* Bits 9-0: Baud Rate Prescaler */
+#define CAN_BTR_BRP_MASK (0x03ff << CAN_BTR_BRP_SHIFT)
+#define CAN_BTR_TS1_SHIFT (16) /* Bits 19-16: Time Segment 1 */
+#define CAN_BTR_TS1_MASK (0x0f << CAN_BTR_TS1_SHIFT)
+#define CAN_BTR_TS2_SHIFT (20) /* Bits 22-20: Time Segment 2 */
+#define CAN_BTR_TS2_MASK (7 << CAN_BTR_TS2_SHIFT)
+#define CAN_BTR_SJW_SHIFT (24) /* Bits 25-24: Resynchronization Jump Width */
+#define CAN_BTR_SJW_MASK (3 << CAN_BTR_SJW_SHIFT)
+#define CAN_BTR_LBKM (1 << 30) /* Bit 30: Loop Back Mode (Debug) */
+#define CAN_BTR_SILM (1 << 31) /* Bit 31: Silent Mode (Debug) */
+
+#define CAN_BTR_BRP_MAX (1024) /* Maximum BTR value (without decrement) */
+#define CAN_BTR_TSEG1_MAX (16) /* Maximum TSEG1 value (without decrement) */
+#define CAN_BTR_TSEG2_MAX (8) /* Maximum TSEG2 value (without decrement) */
+
+/* TX mailbox identifier register */
+
+#define CAN_TIR_TXRQ (1 << 0) /* Bit 0: Transmit Mailbox Request */
+#define CAN_TIR_RTR (1 << 1) /* Bit 1: Remote Transmission Request */
+#define CAN_TIR_IDE (1 << 2) /* Bit 2: Identifier Extension */
+#define CAN_TIR_EXID_SHIFT (3) /* Bit 3-31: Extended Identifier */
+#define CAN_TIR_EXID_MASK (0x1fffffff << CAN_TIR_EXID_SHIFT)
+#define CAN_TIR_STID_SHIFT (21) /* Bits 21-31: Standard Identifier */
+#define CAN_TIR_STID_MASK (0x07ff << CAN_TIR_STID_SHIFT)
+
+/* Mailbox data length control and time stamp register */
+
+#define CAN_TDTR_DLC_SHIFT (0) /* Bits 3:0: Data Length Code */
+#define CAN_TDTR_DLC_MASK (0x0f << CAN_TDTR_DLC_SHIFT)
+#define CAN_TDTR_TGT (1 << 8) /* Bit 8: Transmit Global Time */
+#define CAN_TDTR_TIME_SHIFT (16) /* Bits 31:16: Message Time Stamp */
+#define CAN_TDTR_TIME_MASK (0xffff << CAN_TDTR_TIME_SHIFT)
+
+/* Mailbox data low register */
+
+#define CAN_TDLR_DATA0_SHIFT (0) /* Bits 7-0: Data Byte 0 */
+#define CAN_TDLR_DATA0_MASK (0xff << CAN_TDLR_DATA0_SHIFT)
+#define CAN_TDLR_DATA1_SHIFT (8) /* Bits 15-8: Data Byte 1 */
+#define CAN_TDLR_DATA1_MASK (0xff << CAN_TDLR_DATA1_SHIFT)
+#define CAN_TDLR_DATA2_SHIFT (16) /* Bits 23-16: Data Byte 2 */
+#define CAN_TDLR_DATA2_MASK (0xff << CAN_TDLR_DATA2_SHIFT)
+#define CAN_TDLR_DATA3_SHIFT (24) /* Bits 31-24: Data Byte 3 */
+#define CAN_TDLR_DATA3_MASK (0xff << CAN_TDLR_DATA3_SHIFT)
+
+/* Mailbox data high register */
+
+#define CAN_TDHR_DATA4_SHIFT (0) /* Bits 7-0: Data Byte 4 */
+#define CAN_TDHR_DATA4_MASK (0xff << CAN_TDHR_DATA4_SHIFT)
+#define CAN_TDHR_DATA5_SHIFT (8) /* Bits 15-8: Data Byte 5 */
+#define CAN_TDHR_DATA5_MASK (0xff << CAN_TDHR_DATA5_SHIFT)
+#define CAN_TDHR_DATA6_SHIFT (16) /* Bits 23-16: Data Byte 6 */
+#define CAN_TDHR_DATA6_MASK (0xff << CAN_TDHR_DATA6_SHIFT)
+#define CAN_TDHR_DATA7_SHIFT (24) /* Bits 31-24: Data Byte 7 */
+#define CAN_TDHR_DATA7_MASK (0xff << CAN_TDHR_DATA7_SHIFT)
+
+/* Rx FIFO mailbox identifier register */
+
+#define CAN_RIR_RTR (1 << 1) /* Bit 1: Remote Transmission Request */
+#define CAN_RIR_IDE (1 << 2) /* Bit 2: Identifier Extension */
+#define CAN_RIR_EXID_SHIFT (3) /* Bit 3-31: Extended Identifier */
+#define CAN_RIR_EXID_MASK (0x1fffffff << CAN_RIR_EXID_SHIFT)
+#define CAN_RIR_STID_SHIFT (21) /* Bits 21-31: Standard Identifier */
+#define CAN_RIR_STID_MASK (0x07ff << CAN_RIR_STID_SHIFT)
+
+/* Receive FIFO mailbox data length control and time stamp register */
+
+#define CAN_RDTR_DLC_SHIFT (0) /* Bits 3:0: Data Length Code */
+#define CAN_RDTR_DLC_MASK (0x0f << CAN_RDTR_DLC_SHIFT)
+#define CAN_RDTR_FM_SHIFT (8) /* Bits 15-8: Filter Match Index */
+#define CAN_RDTR_FM_MASK (0xff << CAN_RDTR_FM_SHIFT)
+#define CAN_RDTR_TIME_SHIFT (16) /* Bits 31:16: Message Time Stamp */
+#define CAN_RDTR_TIME_MASK (0xffff << CAN_RDTR_TIME_SHIFT)
+
+/* Receive FIFO mailbox data low register */
+
+#define CAN_RDLR_DATA0_SHIFT (0) /* Bits 7-0: Data Byte 0 */
+#define CAN_RDLR_DATA0_MASK (0xff << CAN_RDLR_DATA0_SHIFT)
+#define CAN_RDLR_DATA1_SHIFT (8) /* Bits 15-8: Data Byte 1 */
+#define CAN_RDLR_DATA1_MASK (0xff << CAN_RDLR_DATA1_SHIFT)
+#define CAN_RDLR_DATA2_SHIFT (16) /* Bits 23-16: Data Byte 2 */
+#define CAN_RDLR_DATA2_MASK (0xff << CAN_RDLR_DATA2_SHIFT)
+#define CAN_RDLR_DATA3_SHIFT (24) /* Bits 31-24: Data Byte 3 */
+#define CAN_RDLR_DATA3_MASK (0xff << CAN_RDLR_DATA3_SHIFT)
+
+/* Receive FIFO mailbox data high register */
+
+#define CAN_RDHR_DATA4_SHIFT (0) /* Bits 7-0: Data Byte 4 */
+#define CAN_RDHR_DATA4_MASK (0xff << CAN_RDHR_DATA4_SHIFT)
+#define CAN_RDHR_DATA5_SHIFT (8) /* Bits 15-8: Data Byte 5 */
+#define CAN_RDHR_DATA5_MASK (0xff << CAN_RDHR_DATA5_SHIFT)
+#define CAN_RDHR_DATA6_SHIFT (16) /* Bits 23-16: Data Byte 6 */
+#define CAN_RDHR_DATA6_MASK (0xff << CAN_RDHR_DATA6_SHIFT)
+#define CAN_RDHR_DATA7_SHIFT (24) /* Bits 31-24: Data Byte 7 */
+#define CAN_RDHR_DATA7_MASK (0xff << CAN_RDHR_DATA7_SHIFT)
+
+/* CAN filter master register */
+
+#define CAN_FMR_FINIT (1 << 0) /* Bit 0: Filter Init Mode */
+#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define CAN_FMR_CAN2SB_SHIFT (8) /* Bits 13-8: CAN2 start bank */
+# define CAN_FMR_CAN2SB_MASK (0x3f << CAN_FMR_CAN2SB_SHIFT)
+#endif
+
+/* CAN filter mode register */
+
+#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define CAN_FM1R_FBM_SHIFT (0) /* Bits 13:0: Filter Mode */
+# define CAN_FM1R_FBM_MASK (0x3fff << CAN_FM1R_FBM_SHIFT)
+#else
+# define CAN_FM1R_FBM_SHIFT (0) /* Bits 27:0: Filter Mode */
+# define CAN_FM1R_FBM_MASK (0x0fffffff << CAN_FM1R_FBM_SHIFT)
+#endif
+
+/* CAN filter scale register */
+
+#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define CAN_FS1R_FSC_SHIFT (0) /* Bits 13:0: Filter Scale Configuration */
+# define CAN_FS1R_FSC_MASK (0x3fff << CAN_FS1R_FSC_SHIFT)
+#else
+# define CAN_FS1R_FSC_SHIFT (0) /* Bits 27:0: Filter Scale Configuration */
+# define CAN_FS1R_FSC_MASK (0x0fffffff << CAN_FS1R_FSC_SHIFT)
+#endif
+
+/* CAN filter FIFO assignment register */
+
+#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define CAN_FFA1R_FFA_SHIFT (0) /* Bits 13:0: Filter FIFO Assignment */
+# define CAN_FFA1R_FFA_MASK (0x3fff << CAN_FFA1R_FFA_SHIFT)
+#else
+# define CAN_FFA1R_FFA_SHIFT (0) /* Bits 27:0: Filter FIFO Assignment */
+# define CAN_FFA1R_FFA_MASK (0x0fffffff << CAN_FFA1R_FFA_SHIFT)
+#endif
+
+/* CAN filter activation register */
+
+#if defined(CONFIG_STM32_CONNECTIVITYLINE) || defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define CAN_FA1R_FACT_SHIFT (0) /* Bits 13:0: Filter Active */
+# define CAN_FA1R_FACT_MASK (0x3fff << CAN_FA1R_FACT_SHIFT)
+#else
+# define CAN_FA1R_FACT_SHIFT (0) /* Bits 27:0: Filter Active */
+# define CAN_FA1R_FACT_MASK (0x0fffffff << CAN_FA1R_FACT_SHIFT)
+#endif
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_CAN_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_dac.h b/nuttx/arch/arm/src/stm32/chip/stm32_dac.h
new file mode 100644
index 000000000..1498c8c93
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_dac.h
@@ -0,0 +1,256 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_dac.h
+ *
+ * Copyright (C) 2011 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_STM32_CHIP_STM32_DAC_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_DAC_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_DAC_CR_OFFSET 0x0000 /* DAC control register */
+#define STM32_DAC_SWTRIGR_OFFSET 0x0004 /* DAC software trigger register */
+#define STM32_DAC_DHR12R1_OFFSET 0x0008 /* DAC channel1 12-bit right-aligned data holding register */
+#define STM32_DAC_DHR12L1_OFFSET 0x000c /* DAC channel1 12-bit left aligned data holding register */
+#define STM32_DAC_DHR8R1_OFFSET 0x0010 /* DAC channel1 8-bit right aligned data holding register */
+#define STM32_DAC_DHR12R2_OFFSET 0x0014 /* DAC channel2 12-bit right aligned data holding register */
+#define STM32_DAC_DHR12L_OFFSET 0x0018 /* DAC channel2 12-bit left aligned data holding register */
+#define STM32_DAC_DHR8R2_OFFSET 0x001c /* DAC channel2 8-bit right-aligned data holding register */
+#define STM32_DAC_DHR12RD_OFFSET 0x0020 /* Dual DAC 12-bit right-aligned data holding register */
+#define STM32_DAC_DHR12LD_OFFSET 0x0024 /* DUAL DAC 12-bit left aligned data holding register */
+#define STM32_DAC_DHR8RD_OFFSET 0x0028 /* DUAL DAC 8-bit right aligned data holding register */
+#define STM32_DAC_DOR1_OFFSET 0x002c /* DAC channel1 data output register */
+#define STM32_DAC_DOR2_OFFSET 0x0030 /* DAC channel2 data output register */
+#define STM32_DAC_SR_OFFSET 0x0034 /* DAC status register */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_DAC_CR (STM32_DAC_BASE+STM32_DAC_CR_OFFSET)
+#define STM32_DAC_SWTRIGR (STM32_DAC_BASE+STM32_DAC_SWTRIGR_OFFSET)
+#define STM32_DAC_DHR12R1 (STM32_DAC_BASE+STM32_DAC_DHR12R1_OFFSET)
+#define STM32_DAC_DHR12L1 (STM32_DAC_BASE+STM32_DAC_DHR12L1_OFFSET)
+#define STM32_DAC_DHR8R1 (STM32_DAC_BASE+STM32_DAC_DHR8R1_OFFSET)
+#define STM32_DAC_DHR12R2 (STM32_DAC_BASE+STM32_DAC_DHR12R2_OFFSET)
+#define STM32_DAC_DHR12L (STM32_DAC_BASE+STM32_DAC_DHR12L_OFFSET)
+#define STM32_DAC_DHR8R2 (STM32_DAC_BASE+STM32_DAC_DHR8R2_OFFSET)
+#define STM32_DAC_DHR12RD (STM32_DAC_BASE+STM32_DAC_DHR12RD_OFFSET)
+#define STM32_DAC_DHR12LD (STM32_DAC_BASE+STM32_DAC_DHR12LD_OFFSET)
+#define STM32_DAC_DHR8RD (STM32_DAC_BASE+STM32_DAC_DHR8RD_OFFSET)
+#define STM32_DAC_DOR1 (STM32_DAC_BASE+STM32_DAC_DOR1_OFFSET)
+#define STM32_DAC_DOR2 (STM32_DAC_BASE+STM32_DAC_DOR2_OFFSET)
+#define STM32_DAC_SR (STM32_DAC_BASE+STM32_DAC_SR_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* DAC control register */
+/* These definitions may be used for 16-bit values of either channel */
+
+#define DAC_CR_EN (1 << 0) /* Bit 0: DAC channel1 enable */
+#define DAC_CR_BOFF (1 << 1) /* Bit 1: DAC channel1 output buffer disable */
+#define DAC_CR_TSEL_SHIFT (3) /* Bits 3-5: DAC channel1 trigger selection */
+#define DAC_CR_TSEL_MASK (7 << DAC_CR_TSEL_SHIFT)
+# define DAC_CR_TSEL_TIM6 (0 << DAC_CR_TSEL_SHIFT) /* Timer 6 TRGO event */
+#ifdef CONFIG_STM32_CONNECTIVITYLINE
+# define DAC_CR_TSEL_TIM3 (1 << DAC_CR_TSEL_SHIFT) /* Timer 3 TRGO event */
+#else
+# define DAC_CR_TSEL_TIM8 (1 << DAC_CR_TSEL_SHIFT) /* Timer 8 TRGO event */
+#endif
+# define DAC_CR_TSEL_TIM7 (2 << DAC_CR_TSEL_SHIFT) /* Timer 7 TRGO event */
+# define DAC_CR_TSEL_TIM5 (3 << DAC_CR_TSEL_SHIFT) /* Timer 5 TRGO event */
+# define DAC_CR_TSEL_TIM2 (4 << DAC_CR_TSEL_SHIFT) /* Timer 2 TRGO event */
+# define DAC_CR_TSEL_TIM4 (5 << DAC_CR_TSEL_SHIFT) /* Timer 4 TRGO event */
+# define DAC_CR_TSEL_EXT9 (6 << DAC_CR_TSEL_SHIFT) /* External line9 */
+# define DAC_CR_TSEL_SW (7 << DAC_CR_TSEL_SHIFT) /* Software trigger */
+#define DAC_CR_WAVE_SHIFT (6) /* Bits 6-7: DAC channel1 noise/triangle wave generation */enable
+#define DAC_CR_WAVE_MASK (3 << DAC_CR_WAVE_SHIFT)
+# define DAC_CR_WAVE_DISABLED (0 << DAC_CR_WAVE_SHIFT) /* Wave generation disabled */
+# define DAC_CR_WAVE_NOISE (1 << DAC_CR_WAVE_SHIFT) /* Noise wave generation enabled */
+# define DAC_CR_WAVE_TRIANGLE (2 << DAC_CR_WAVE_SHIFT) /* Triangle wave generation enabled */
+#define DAC_CR_MAMP_SHIFT (8) /* Bits 8-11: DAC channel1 mask/amplitude selector */
+#define DAC_CR_MAMP_MASK (15 << DAC_CR_MAMP_SHIFT)
+# define DAC_CR_MAMP_AMP1 (0 << DAC_CR_MAMP1_SHIFT) /* Unmask bit0 of LFSR/triangle amplitude=1 */
+# define DAC_CR_MAMP_AMP3 (1 << DAC_CR_MAMP_SHIFT) /* Unmask bits[1:0] of LFSR/triangle amplitude=3 */
+# define DAC_CR_MAMP_AMP7 (2 << DAC_CR_MAMP_SHIFT) /* Unmask bits[2:0] of LFSR/triangle amplitude=7 */
+# define DAC_CR_MAMP_AMP15 (3 << DAC_CR_MAMP_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */
+# define DAC_CR_MAMP_AMP31 (4 << DAC_CR_MAMP_SHIFT) /* Unmask bits[4:0] of LFSR/triangle amplitude=31 */
+# define DAC_CR_MAMP_AMP63 (5 << DAC_CR_MAMP_SHIFT) /* Unmask bits[5:0] of LFSR/triangle amplitude=63 */
+# define DAC_CR_MAMP_AMP127 (6 << DAC_CR_MAMP_SHIFT) /* Unmask bits[6:0] of LFSR/triangle amplitude=127 */
+# define DAC_CR_MAMP_AMP255 (7 << DAC_CR_MAMP_SHIFT) /* Unmask bits[7:0] of LFSR/triangle amplitude=255 */
+# define DAC_CR_MAMP_AMP511 (8 << DAC_CR_MAMP_SHIFT) /* Unmask bits[8:0] of LFSR/triangle amplitude=511 */
+# define DAC_CR_MAMP_AMP1023 (9 << DAC_CR_MAMP_SHIFT) /* Unmask bits[9:0] of LFSR/triangle amplitude=1023 */
+# define DAC_CR_MAMP_AMP2047 (10 << DAC_CR_MAMP_SHIFT) /* Unmask bits[10:0] of LFSR/triangle amplitude=2047 */
+# define DAC_CR_MAMP_AMP4095 (11 << DAC_CR_MAMP_SHIFT) /* Unmask bits[11:0] of LFSR/triangle amplitude=4095 */
+#define DAC_CR_DMAEN (1 << 12) /* Bit 12: DAC channel1 DMA enable */
+#define DAC_CR_DMAUDRIE (1 << 13) /* Bit 13: DAC channel1 DMA Underrun Interrupt enable */
+
+/* These definitions may be used with the full, 32-bit register */
+
+#define DAC_CR_EN1 (1 << 0) /* Bit 0: DAC channel1 enable */
+#define DAC_CR_BOFF1 (1 << 1) /* Bit 1: DAC channel1 output buffer disable */
+#define DAC_CR_TSEL1_SHIFT (3) /* Bits 3-5: DAC channel1 trigger selection */
+#define DAC_CR_TSEL1_MASK (7 << DAC_CR_TSEL1_SHIFT)
+# define DAC_CR_TSEL1_TIM6 (0 << DAC_CR_TSEL1_SHIFT) /* Timer 6 TRGO event */
+# define DAC_CR_TSEL1_TIM8 (1 << DAC_CR_TSEL1_SHIFT) /* Timer 8 TRGO event */
+# define DAC_CR_TSEL1_TIM7 (2 << DAC_CR_TSEL1_SHIFT) /* Timer 7 TRGO event */
+# define DAC_CR_TSEL1_TIM5 (3 << DAC_CR_TSEL1_SHIFT) /* Timer 5 TRGO event */
+# define DAC_CR_TSEL1_TIM2 (4 << DAC_CR_TSEL1_SHIFT) /* Timer 2 TRGO event */
+# define DAC_CR_TSEL1_TIM4 (5 << DAC_CR_TSEL1_SHIFT) /* Timer 4 TRGO event */
+# define DAC_CR_TSEL1_EXT9 (6 << DAC_CR_TSEL1_SHIFT) /* External line9 */
+# define DAC_CR_TSEL1_SW (7 << DAC_CR_TSEL1_SHIFT) /* Software trigger */
+#define DAC_CR_WAVE1_SHIFT (6) /* Bits 6-7: DAC channel1 noise/triangle wave generation */enable
+#define DAC_CR_WAVE1_MASK (3 << DAC_CR_WAVE1_SHIFT)
+# define DAC_CR_WAVE1_DISABLED (0 << DAC_CR_WAVE1_SHIFT) /* Wave generation disabled */
+# define DAC_CR_WAVE1_NOISE (1 << DAC_CR_WAVE1_SHIFT) /* Noise wave generation enabled */
+# define DAC_CR_WAVE1_TRIANGLE (2 << DAC_CR_WAVE1_SHIFT) /* Triangle wave generation enabled */
+#define DAC_CR_MAMP1_SHIFT (8) /* Bits 8-11: DAC channel1 mask/amplitude selector */
+#define DAC_CR_MAMP1_MASK (15 << DAC_CR_MAMP1_SHIFT)
+# define DAC_CR_MAMP1_AMP1 (0 << DAC_CR_MAMP1_SHIFT) /* Unmask bit0 of LFSR/triangle amplitude=1 */
+# define DAC_CR_MAMP1_AMP3 (1 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[1:0] of LFSR/triangle amplitude=3 */
+# define DAC_CR_MAMP1_AMP7 (2 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[2:0] of LFSR/triangle amplitude=7 */
+# define DAC_CR_MAMP1_AMP15 (3 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */
+# define DAC_CR_MAMP1_AMP31 (4 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[4:0] of LFSR/triangle amplitude=31 */
+# define DAC_CR_MAMP1_AMP63 (5 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[5:0] of LFSR/triangle amplitude=63 */
+# define DAC_CR_MAMP1_AMP127 (6 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[6:0] of LFSR/triangle amplitude=127 */
+# define DAC_CR_MAMP1_AMP255 (7 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[7:0] of LFSR/triangle amplitude=255 */
+# define DAC_CR_MAMP1_AMP511 (8 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[8:0] of LFSR/triangle amplitude=511 */
+# define DAC_CR_MAMP1_AMP1023 (9 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[9:0] of LFSR/triangle amplitude=1023 */
+# define DAC_CR_MAMP1_AMP2047 (10 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[10:0] of LFSR/triangle amplitude=2047 */
+# define DAC_CR_MAMP1_AMP4095 (11 << DAC_CR_MAMP1_SHIFT) /* Unmask bits[11:0] of LFSR/triangle amplitude=4095 */
+#define DAC_CR_DMAEN1 (1 << 12) /* Bit 12: DAC channel1 DMA enable */
+#define DAC_CR_DMAUDRIE1 (1 << 13) /* Bit 13: DAC channel1 DMA Underrun Interrupt enable */
+
+#define DAC_CR_EN2 (1 << 16) /* Bit 16: DAC channel2 enable */
+#define DAC_CR_BOFF2 (1 << 17) /* Bit 17: DAC channel2 output buffer disable */
+#define DAC_CR_TEN2 (1 << 18) /* Bit 18: DAC channel2 trigger enable */
+#define DAC_CR_TSEL2_SHIFT (19) /* Bits 19-21: DAC channel2 trigger selection */
+#define DAC_CR_TSEL2_MASK (7 << DAC_CR_TSEL2_SHIFT)
+# define DAC_CR_TSEL2_TIM6 (0 << DAC_CR_TSEL2_SHIFT) /* Timer 6 TRGO event */
+# define DAC_CR_TSEL2_TIM8 (1 << DAC_CR_TSEL2_SHIFT) /* Timer 8 TRGO event */
+# define DAC_CR_TSEL2_TIM7 (2 << DAC_CR_TSEL2_SHIFT) /* Timer 7 TRGO event */
+# define DAC_CR_TSEL2_TIM5 (3 << DAC_CR_TSEL2_SHIFT) /* Timer 5 TRGO event */
+# define DAC_CR_TSEL2_TIM2 (4 << DAC_CR_TSEL2_SHIFT) /* Timer 2 TRGO event */
+# define DAC_CR_TSEL2_TIM4 (5 << DAC_CR_TSEL2_SHIFT) /* Timer 4 TRGO event */
+# define DAC_CR_TSEL2_EXT9 (6 << DAC_CR_TSEL2_SHIFT) /* External line9 */
+# define DAC_CR_TSEL2_SW (7 << DAC_CR_TSEL2_SHIFT) /* Software trigger */
+#define DAC_CR_WAVE2_SHIFT (22) /* Bit 22-23: DAC channel2 noise/triangle wave generation enable */
+#define DAC_CR_WAVE2_MASK (3 << DAC_CR_WAVE2_SHIFT)
+# define DAC_CR_WAVE2_DISABLED (0 << DAC_CR_WAVE2_SHIFT) /* Wave generation disabled */
+# define DAC_CR_WAVE2_NOISE (1 << DAC_CR_WAVE2_SHIFT) /* Noise wave generation enabled */
+# define DAC_CR_WAVE2_TRIANGLE (2 << DAC_CR_WAVE2_SHIFT) /* Triangle wave generation enabled */
+#define DAC_CR_MAMP2_SHIFT (24) /* Bit 24-27: DAC channel2 mask/amplitude selector */
+#define DAC_CR_MAMP2_MASK (15 << DAC_CR_MAMP2_SHIFT)
+# define DAC_CR_MAMP2_AMP1 (0 << DAC_CR_MAMP2_SHIFT) /* Unmask bit0 of LFSR/triangle amplitude=1 */
+# define DAC_CR_MAMP2_AMP3 (1 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[1:0] of LFSR/triangle amplitude=3 */
+# define DAC_CR_MAMP2_AMP7 (2 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[2:0] of LFSR/triangle amplitude=7 */
+# define DAC_CR_MAMP2_AMP15 (3 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[3:0] of LFSR/triangle amplitude=15 */
+# define DAC_CR_MAMP2_AMP31 (4 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[4:0] of LFSR/triangle amplitude=31 */
+# define DAC_CR_MAMP2_AMP63 (5 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[5:0] of LFSR/triangle amplitude=63 */
+# define DAC_CR_MAMP2_AMP127 (6 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[6:0] of LFSR/triangle amplitude=127 */
+# define DAC_CR_MAMP2_AMP255 (7 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[7:0] of LFSR/triangle amplitude=255 */
+# define DAC_CR_MAMP2_AMP511 (8 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[8:0] of LFSR/triangle amplitude=511 */
+# define DAC_CR_MAMP2_AMP1023 (9 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[9:0] of LFSR/triangle amplitude=1023 */
+# define DAC_CR_MAMP2_AMP2047 (10 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[10:0] of LFSR/triangle amplitude=2047 */
+# define DAC_CR_MAMP2_AMP4095 (11 << DAC_CR_MAMP2_SHIFT) /* Unmask bits[11:0] of LFSR/triangle amplitude=4095 */
+#define DAC_CR_DMAEN2 (1 << 28) /* Bit 28: DAC channel2 DMA enable */
+#define DAC_CR_DMAUDRIE2 (1 << 29) /* Bits 29: DAC channel2 DMA underrun interrupt enable */
+
+/* DAC software trigger register */
+
+#define DAC_SWTRIGR_SWTRIG(n) (1 << ((n)-1))
+#define DAC_SWTRIGR_SWTRIG1 (1 << 0) /* Bit 0: DAC channel1 software trigger */
+#define DAC_SWTRIGR_SWTRIG2 (1 << 1) /* Bit 1: DAC channel2 software trigger */
+
+/* DAC channel1/2 12-bit right-aligned data holding register */
+
+#define DAC_DHR12R_MASK (0x0fff)
+
+/* DAC channel1/2 12-bit left aligned data holding register */
+
+#define DAC_DHR12L_MASK (0xfff0)
+
+/* DAC channel1/2 8-bit right aligned data holding register */
+
+#define DAC_DHR8R_MASK (0x00ff)
+
+/* Dual DAC 12-bit right-aligned data holding register */
+
+#define DAC_DHR12RD_DACC_SHIFT(n) (1 << (((n)-1) << 4))
+#define DAC_DHR12RD_DACC_MASK(n) (0xfff << DAC_DHR12RD_DACC_SHIFT(n))
+
+#define DAC_DHR12RD_DACC1_SHIFT (0) /* Bits 0-11: DAC channel1 12-bit right-aligned data */
+#define DAC_DHR12RD_DACC1_MASK (0xfff << DAC_DHR12RD_DACC2_SHIFT)
+#define DAC_DHR12RD_DACC2_SHIFT (16) /* Bits 16-27: DAC channel2 12-bit right-aligned data */
+#define DAC_DHR12RD_DACC2_MASK (0xfff << DAC_DHR12RD_DACC2_SHIFT)
+
+/* Dual DAC 12-bit left-aligned data holding register */
+
+#define DAC_DHR12LD_DACC_SHIFT(n) ((1 << (((n)-1) << 4)) + 4)
+#define DAC_DHR12LD_DACC_MASK(n) (0xfff << DAC_DHR12LD_DACC_SHIFT(n))
+
+#define DAC_DHR12LD_DACC1_SHIFT (4) /* Bits 4-15: DAC channel1 12-bit left-aligned data */
+#define DAC_DHR12LD_DACC1_MASK (0xfff << DAC_DHR12LD_DACC1_SHIFT)
+#define DAC_DHR12LD_DACC2_SHIFT (20) /* Bits 20-31: DAC channel2 12-bit left-aligned data */
+#define DAC_DHR12LD_DACC2_MASK (0xfff << DAC_DHR12LD_DACC2_SHIFT)
+
+/* DUAL DAC 8-bit right aligned data holding register */
+
+#define DAC_DHR8RD_DACC_SHIFT(n) (1 << (((n)-1) << 3))
+#define DAC_DHR8RD_DACC_MASK(n) (0xff << DAC_DHR8RD_DACC_SHIFT(n))
+
+#define DAC_DHR8RD_DACC1_SHIFT (0) /* Bits 0-7: DAC channel1 8-bit right-aligned data */
+#define DAC_DHR8RD_DACC1_MASK (0xff << DAC_DHR8RD_DACC1_SHIFT)
+#define DAC_DHR8RD_DACC2_SHIFT (8) /* Bits 8-15: DAC channel2 8-bit right-aligned data */
+#define DAC_DHR8RD_DACC2_MASK (0xff << DAC_DHR8RD_DACC2_SHIFT)
+
+/* DAC channel1/2 data output register */
+
+#define DAC_DOR_MASK (0x0fff)
+
+/* DAC status register */
+
+#define DAC_SR_DMAUDR(n) ((1 << (((n)-1) << 4)) + 13)
+#define DAC_SR_DMAUDR1 (1 << 13) /* Bit 13: DAC channel1 DMA underrun flag */
+#define DAC_SR_DMAUDR2 (1 << 29) /* Bit 29: DAC channel2 DMA underrun flag */
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_DAC_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_dbgmcu.h b/nuttx/arch/arm/src/stm32/chip/stm32_dbgmcu.h
new file mode 100644
index 000000000..ff1661313
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_dbgmcu.h
@@ -0,0 +1,144 @@
+/****************************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_dbgmcu.h
+ *
+ * Copyright (C) 2009 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_STM32_CHIP_STM32_DBGMCU_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_DBGMCU_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/****************************************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************************************/
+
+/* Register Addresses *******************************************************************************/
+
+#define STM32_DBGMCU_IDCODE 0xe0042000 /* MCU identifier */
+#define STM32_DBGMCU_CR 0xe0042004 /* MCU debug */
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_DBGMCU_APB1_FZ 0xe0042008 /* Debug MCU APB1 freeze register */
+# define STM32_DBGMCU_APB2_FZ 0xe004200c /* Debug MCU APB2 freeze register */
+#endif
+
+/* Register Bitfield Definitions ********************************************************************/
+
+/* MCU identifier */
+
+#define DBGMCU_IDCODE_DEVID_SHIFT (0) /* Bits 11-0: Device Identifier */
+#define DBGMCU_IDCODE_DEVID_MASK (0x0fff << DBGMCU_IDCODE_DEVID_SHIFT)
+#define DBGMCU_IDCODE_REVID_SHIFT (16) /* Bits 31-16: Revision Identifier */
+#define DBGMCU_IDCODE_REVID_MASK (0xffff << DBGMCU_IDCODE_REVID_SHIFT)
+
+/* MCU debug */
+
+#define DBGMCU_CR_SLEEP (1 << 0) /* Bit 0: Debug Sleep Mode */
+#define DBGMCU_CR_STOP (1 << 1) /* Bit 1: Debug Stop Mode */
+#define DBGMCU_CR_STANDBY (1 << 2) /* Bit 2: Debug Standby mode */
+#define DBGMCU_CR_TRACEIOEN (1 << 5) /* Bit 5: Trace enabled */
+
+#define DBGMCU_CR_TRACEMODE_SHIFT (6) /* Bits 7-6: Trace mode pin assignement */
+#define DBGMCU_CR_TRACEMODE_MASK (3 << DBGMCU_CR_TRACEMODE_SHIFT)
+# define DBGMCU_CR_ASYNCH (0 << DBGMCU_CR_TRACEMODE_SHIFT) /* Asynchronous Mode */
+# define DBGMCU_CR_SYNCH1 (1 << DBGMCU_CR_TRACEMODE_SHIFT) /* Synchronous Mode, TRACEDATA size=1 */
+# define DBGMCU_CR_SYNCH2 (2 << DBGMCU_CR_TRACEMODE_SHIFT) /* Synchronous Mode, TRACEDATA size=2 */
+# define DBGMCU_CR_SYNCH4 (3 << DBGMCU_CR_TRACEMODE_SHIFT) /* Synchronous Mode, TRACEDATA size=4 */
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define DBGMCU_CR_IWDGSTOP (1 << 8) /* Bit 8: Independent Watchdog stopped when core is halted */
+# define DBGMCU_CR_WWDGSTOP (1 << 9) /* Bit 9: Window Watchdog stopped when core is halted */
+# define DBGMCU_CR_TIM1STOP (1 << 10) /* Bit 10: TIM1 stopped when core is halted */
+# define DBGMCU_CR_TIM2STOP (1 << 11) /* Bit 11: TIM2 stopped when core is halted */
+# define DBGMCU_CR_TIM3STOP (1 << 12) /* Bit 12: TIM3 stopped when core is halted */
+# define DBGMCU_CR_TIM4STOP (1 << 13) /* Bit 13: TIM4 stopped when core is halted */
+# define DBGMCU_CR_CAN1STOP (1 << 14) /* Bit 14: CAN1 stopped when core is halted */
+# define DBGMCU_CR_SMBUS1STOP (1 << 15) /* Bit 15: I2C1 SMBUS timeout mode stopped when core is halted */
+# define DBGMCU_CR_SMBUS2STOP (1 << 16) /* Bit 16: I2C2 SMBUS timeout mode stopped when core is halted */
+# define DBGMCU_CR_TIM8STOP (1 << 17) /* Bit 17: TIM8 stopped when core is halted */
+# define DBGMCU_CR_TIM5STOP (1 << 18) /* Bit 18: TIM5 stopped when core is halted */
+# define DBGMCU_CR_TIM6STOP (1 << 19) /* Bit 19: TIM6 stopped when core is halted */
+# define DBGMCU_CR_TIM7STOP (1 << 20) /* Bit 20: TIM7 stopped when core is halted */
+# define DBGMCU_CR_CAN2STOP (1 << 21) /* Bit 21: CAN2 stopped when core is halted */
+#endif
+
+/* Debug MCU APB1 freeze register */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define DBGMCU_APB1_TIM2STOP (1 << 0) /* Bit 0: TIM2 stopped when core is halted */
+# define DBGMCU_APB1_TIM3STOP (1 << 1) /* Bit 1: TIM3 stopped when core is halted */
+# define DBGMCU_APB1_TIM4STOP (1 << 2) /* Bit 2: TIM4 stopped when core is halted */
+# define DBGMCU_APB1_TIM5STOP (1 << 3) /* Bit 3: TIM5 stopped when core is halted */
+# define DBGMCU_APB1_TIM6STOP (1 << 4) /* Bit 4: TIM6 stopped when core is halted */
+# define DBGMCU_APB1_TIM7STOP (1 << 5) /* Bit 5: TIM7 stopped when core is halted */
+# define DBGMCU_APB1_TIM12STOP (1 << 6) /* Bit 6: TIM12 stopped when core is halted */
+# define DBGMCU_APB1_TIM13STOP (1 << 7) /* Bit 7: TIM13 stopped when core is halted */
+# define DBGMCU_APB1_TIM14STOP (1 << 8) /* Bit 7: TIM14 stopped when core is halted */
+# define DBGMCU_CR_RTCSTOP (1 << 10) /* Bit 11: RTC stopped when Core is halted */
+# define DBGMCU_CR_WWDGSTOP (1 << 11) /* Bit 11: Window Watchdog stopped when core is halted */
+# define DBGMCU_CR_IWDGSTOP (1 << 12) /* Bit 12: Independent Watchdog stopped when core is halted */
+# define DBGMCU_APB1_I2C1STOP (1 << 21) /* Bit 21: SMBUS timeout mode stopped when Core is halted */
+# define DBGMCU_APB1_I2C2STOP (1 << 22) /* Bit 22: SMBUS timeout mode stopped when Core is halted */
+# define DBGMCU_APB1_I2C3STOP (1 << 23) /* Bit 23: SMBUS timeout mode stopped when Core is halted */
+# define DBGMCU_APB1_CAN1STOP (1 << 25) /* Bit 25: CAN1 stopped when core is halted */
+# define DBGMCU_APB1_CAN2STOP (1 << 26) /* Bit 26: CAN2 stopped when core is halted */
+#endif
+
+/* Debug MCU APB2 freeze register */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define DBGMCU_APB2_TIM1STOP (1 << 0) /* Bit 0: TIM1 stopped when core is halted */
+# define DBGMCU_APB2_TIM8STOP (1 << 1) /* Bit 1: TIM8 stopped when core is halted */
+# define DBGMCU_APB2_TIM9STOP (1 << 16) /* Bit 16: TIM9 stopped when core is halted */
+# define DBGMCU_APB2_TIM10STOP (1 << 17) /* Bit 17: TIM10 stopped when core is halted */
+# define DBGMCU_APB2_TIM11STOP (1 << 18) /* Bit 18: TIM11 stopped when core is halted */
+#endif
+
+/****************************************************************************************************
+ * Public Types
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Public Data
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Public Functions
+ ****************************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_DBGMCU_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_eth.h b/nuttx/arch/arm/src/stm32/chip/stm32_eth.h
new file mode 100644
index 000000000..431144009
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_eth.h
@@ -0,0 +1,829 @@
+/****************************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_eth.h
+ *
+ * Copyright (C) 2011-2012 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_STM32_CHIP_STM32_ETH_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_ETH_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+#if STM32_NETHERNET > 0
+
+/****************************************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************************************/
+/* Register Offsets *********************************************************************************/
+/* MAC Registers */
+
+#define STM32_ETH_MACCR_OFFSET 0x0000 /* Ethernet MAC configuration register */
+#define STM32_ETH_MACFFR_OFFSET 0x0004 /* Ethernet MAC frame filter register */
+#define STM32_ETH_MACHTHR_OFFSET 0x0008 /* Ethernet MAC hash table high register */
+#define STM32_ETH_MACHTLR_OFFSET 0x000c /* Ethernet MAC hash table low register */
+#define STM32_ETH_MACMIIAR_OFFSET 0x0010 /* Ethernet MAC MII address register */
+#define STM32_ETH_MACMIIDR_OFFSET 0x0014 /* Ethernet MAC MII data register */
+#define STM32_ETH_MACFCR_OFFSET 0x0018 /* Ethernet MAC flow control register */
+#define STM32_ETH_MACVLANTR_OFFSET 0x001c /* Ethernet MAC VLAN tag register */
+#define STM32_ETH_MACRWUFFR_OFFSET 0x0028 /* Ethernet MAC remote wakeup frame filter reg */
+#define STM32_ETH_MACPMTCSR_OFFSET 0x002c /* Ethernet MAC PMT control and status register */
+#define STM32_ETH_MACDBGR_OFFSET 0x0034 /* Ethernet MAC debug register */
+#define STM32_ETH_MACSR_OFFSET 0x0038 /* Ethernet MAC interrupt status register */
+#define STM32_ETH_MACIMR_OFFSET 0x003c /* Ethernet MAC interrupt mask register */
+#define STM32_ETH_MACA0HR_OFFSET 0x0040 /* Ethernet MAC address 0 high register */
+#define STM32_ETH_MACA0LR_OFFSET 0x0044 /* Ethernet MAC address 0 low register */
+#define STM32_ETH_MACA1HR_OFFSET 0x0048 /* Ethernet MAC address 1 high register */
+#define STM32_ETH_MACA1LR_OFFSET 0x004c /* Ethernet MAC address1 low register */
+#define STM32_ETH_MACA2HR_OFFSET 0x0050 /* Ethernet MAC address 2 high register */
+#define STM32_ETH_MACA2LR_OFFSET 0x0054 /* Ethernet MAC address 2 low register */
+#define STM32_ETH_MACA3HR_OFFSET 0x0058 /* Ethernet MAC address 3 high register */
+#define STM32_ETH_MACA3LR_OFFSET 0x005c /* Ethernet MAC address 3 low register */
+
+/* MMC Registers */
+
+#define STM32_ETH_MMCCR_OFFSET 0x0100 /* Ethernet MMC control register */
+#define STM32_ETH_MMCRIR_OFFSET 0x0104 /* Ethernet MMC receive interrupt register */
+#define STM32_ETH_MMCTIR_OFFSET 0x0108 /* Ethernet MMC transmit interrupt register */
+#define STM32_ETH_MMCRIMR_OFFSET 0x010c /* Ethernet MMC receive interrupt mask register */
+#define STM32_ETH_MMCTIMR_OFFSET 0x0110 /* Ethernet MMC transmit interrupt mask register */
+#define STM32_ETH_MMCTGFSCCR_OFFSET 0x014c /* Ethernet MMC transmitted good frames counter register (single collision) */
+#define STM32_ETH_MMCTGFMSCCR_OFFSET 0x0150 /* Ethernet MMC transmitted good frames counter register (multiple-collision) */
+#define STM32_ETH_MMCTGFCR_OFFSET 0x0168 /* Ethernet MMC transmitted good frames counter register */
+#define STM32_ETH_MMCRFCECR_OFFSET 0x0194 /* Ethernet MMC received frames with CRC error counter register */
+#define STM32_ETH_MMCRFAECR_OFFSET 0x0198 /* Ethernet MMC received frames with alignment error counter */
+#define STM32_ETH_MMCRGUFCR_OFFSET 0x01c4 /* MMC received good unicast frames counter register */
+
+/* IEEE 1588 time stamp registers */
+
+#define STM32_ETH_PTPTSCR_OFFSET 0x0700 /* Ethernet PTP time stamp control register */
+#define STM32_ETH_PTPSSIR_OFFSET 0x0704 /* Ethernet PTP subsecond increment register */
+#define STM32_ETH_PTPTSHR_OFFSET 0x0708 /* Ethernet PTP time stamp high register */
+#define STM32_ETH_PTPTSLR_OFFSET 0x070c /* Ethernet PTP time stamp low register */
+#define STM32_ETH_PTPTSHUR_OFFSET 0x0710 /* Ethernet PTP time stamp high update register */
+#define STM32_ETH_PTPTSLUR_OFFSET 0x0714 /* Ethernet PTP time stamp low update register */
+#define STM32_ETH_PTPTSAR_OFFSET 0x0718 /* Ethernet PTP time stamp addend register */
+#define STM32_ETH_PTPTTHR_OFFSET 0x071c /* Ethernet PTP target time high register */
+#define STM32_ETH_PTPTTLR_OFFSET 0x0720 /* Ethernet PTP target time low register */
+#define STM32_ETH_PTPTSSR_OFFSET 0x0728 /* Ethernet PTP time stamp status register */
+#define STM32_ETH_PTPPPSCR_OFFSET 0x072c /* Ethernet PTP PPS control register */
+
+/* DMA Registers */
+
+#define STM32_ETH_DMABMR_OFFSET 0x1000 /* Ethernet DMA bus mode register */
+#define STM32_ETH_DMATPDR_OFFSET 0x1004 /* Ethernet DMA transmit poll demand register */
+#define STM32_ETH_DMARPDR_OFFSET 0x1008 /* Ethernet DMA receive poll demand register */
+#define STM32_ETH_DMARDLAR_OFFSET 0x100c /* Ethernet DMA receive descriptor list address register */
+#define STM32_ETH_DMATDLAR_OFFSET 0x1010 /* Ethernet DMA transmit descriptor list address register */
+#define STM32_ETH_DMASR_OFFSET 0x1014 /* Ethernet DMA status register */
+#define STM32_ETH_DMAOMR_OFFSET 0x1018 /* Ethernet DMA operation mode register */
+#define STM32_ETH_DMAIER_OFFSET 0x101c /* Ethernet DMA interrupt enable register */
+#define STM32_ETH_DMAMFBOC_OFFSET 0x1020 /* Ethernet DMA missed frame and buffer overflow counter register */
+#define STM32_ETH_DMARSWTR_OFFSET 0x1024 /* Ethernet DMA receive status watchdog timer register */
+#define STM32_ETH_DMACHTDR_OFFSET 0x1048 /* Ethernet DMA current host transmit descriptor register */
+#define STM32_ETH_DMACHRDR_OFFSET 0x104c /* Ethernet DMA current host receive descriptor register */
+#define STM32_ETH_DMACHTBAR_OFFSET 0x1050 /* Ethernet DMA current host transmit buffer address register */
+#define STM32_ETH_DMACHRBAR_OFFSET 0x1054 /* Ethernet DMA current host receive buffer address register */
+
+/* Register Base Addresses **************************************************************************/
+/* MAC Registers */
+
+#define STM32_ETH_MACCR (STM32_ETHERNET_BASE+STM32_ETH_MACCR_OFFSET)
+#define STM32_ETH_MACFFR (STM32_ETHERNET_BASE+STM32_ETH_MACFFR_OFFSET)
+#define STM32_ETH_MACHTHR (STM32_ETHERNET_BASE+STM32_ETH_MACHTHR_OFFSET)
+#define STM32_ETH_MACHTLR (STM32_ETHERNET_BASE+STM32_ETH_MACHTLR_OFFSET)
+#define STM32_ETH_MACMIIAR (STM32_ETHERNET_BASE+STM32_ETH_MACMIIAR_OFFSET)
+#define STM32_ETH_MACMIIDR (STM32_ETHERNET_BASE+STM32_ETH_MACMIIDR_OFFSET)
+#define STM32_ETH_MACFCR (STM32_ETHERNET_BASE+STM32_ETH_MACFCR_OFFSET)
+#define STM32_ETH_MACVLANTR (STM32_ETHERNET_BASE+STM32_ETH_MACVLANTR_OFFSET)
+#define STM32_ETH_MACRWUFFR (STM32_ETHERNET_BASE+STM32_ETH_MACRWUFFR_OFFSET)
+#define STM32_ETH_MACPMTCSR (STM32_ETHERNET_BASE+STM32_ETH_MACPMTCSR_OFFSET)
+#define STM32_ETH_MACDBGR (STM32_ETHERNET_BASE+STM32_ETH_MACDBGR_OFFSET)
+#define STM32_ETH_MACSR (STM32_ETHERNET_BASE+STM32_ETH_MACSR_OFFSET)
+#define STM32_ETH_MACIMR (STM32_ETHERNET_BASE+STM32_ETH_MACIMR_OFFSET)
+#define STM32_ETH_MACA0HR (STM32_ETHERNET_BASE+STM32_ETH_MACA0HR_OFFSET)
+#define STM32_ETH_MACA0LR (STM32_ETHERNET_BASE+STM32_ETH_MACA0LR_OFFSET)
+#define STM32_ETH_MACA1HR (STM32_ETHERNET_BASE+STM32_ETH_MACA1HR_OFFSET)
+#define STM32_ETH_MACA1LR (STM32_ETHERNET_BASE+STM32_ETH_MACA1LR_OFFSET)
+#define STM32_ETH_MACA2HR (STM32_ETHERNET_BASE+STM32_ETH_MACA2HR_OFFSET)
+#define STM32_ETH_MACA2LR (STM32_ETHERNET_BASE+STM32_ETH_MACA2LR_OFFSET)
+#define STM32_ETH_MACA3HR (STM32_ETHERNET_BASE+STM32_ETH_MACA3HR_OFFSET)
+#define STM32_ETH_MACA3LR (STM32_ETHERNET_BASE+STM32_ETH_MACA3LR_OFFSET)
+
+/* MMC Registers */
+
+#define STM32_ETH_MMCC (STM32_ETHERNET_BASE+STM32_ETH_MMCCR_OFFSET)
+#define STM32_ETH_MMCRIR (STM32_ETHERNET_BASE+STM32_ETH_MMCRIR_OFFSET)
+#define STM32_ETH_MMCTIR (STM32_ETHERNET_BASE+STM32_ETH_MMCTIR_OFFSET)
+#define STM32_ETH_MMCRIMR (STM32_ETHERNET_BASE+STM32_ETH_MMCRIMR_OFFSET)
+#define STM32_ETH_MMCTIMR (STM32_ETHERNET_BASE+STM32_ETH_MMCTIMR_OFFSET)
+#define STM32_ETH_MMCTGFSCCR (STM32_ETHERNET_BASE+STM32_ETH_MMCTGFSCCR_OFFSET)
+#define STM32_ETH_MMCTGFMSCCR (STM32_ETHERNET_BASE+STM32_ETH_MMCTGFMSCCR_OFFSET)
+#define STM32_ETH_MMCTGFCR (STM32_ETHERNET_BASE+STM32_ETH_MMCTGFCR_OFFSET)
+#define STM32_ETH_MMCRFCECR (STM32_ETHERNET_BASE+STM32_ETH_MMCRFCECR_OFFSET)
+#define STM32_ETH_MMCRFAECR (STM32_ETHERNET_BASE+STM32_ETH_MMCRFAECR_OFFSET)
+#define STM32_ETH_MMCRGUFCR (STM32_ETHERNET_BASE+STM32_ETH_MMCRGUFCR_OFFSET)
+
+/* IEEE 1588 time stamp registers */
+
+#define STM32_ETH_PTPTSCR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSCR_OFFSET)
+#define STM32_ETH_PTPSSIR (STM32_ETHERNET_BASE+STM32_ETH_PTPSSIR_OFFSET)
+#define STM32_ETH_PTPTSHR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSHR_OFFSET)
+#define STM32_ETH_PTPTSLR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSLR_OFFSET)
+#define STM32_ETH_PTPTSHUR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSHUR_OFFSET)
+#define STM32_ETH_PTPTSLUR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSLUR_OFFSET)
+#define STM32_ETH_PTPTSAR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSAR_OFFSET)
+#define STM32_ETH_PTPTTHR (STM32_ETHERNET_BASE+STM32_ETH_PTPTTHR_OFFSET)
+#define STM32_ETH_PTPTTLR (STM32_ETHERNET_BASE+STM32_ETH_PTPTTLR_OFFSET)
+#define STM32_ETH_PTPTSSR (STM32_ETHERNET_BASE+STM32_ETH_PTPTSSR_OFFSET)
+#define STM32_ETH_PTPPPSCR (STM32_ETHERNET_BASE+STM32_ETH_PTPPPSCR_OFFSET)
+
+/* DMA Registers */
+
+#define STM32_ETH_DMABMR (STM32_ETHERNET_BASE+STM32_ETH_DMABMR_OFFSET)
+#define STM32_ETH_DMATPDR (STM32_ETHERNET_BASE+STM32_ETH_DMATPDR_OFFSET)
+#define STM32_ETH_DMARPDR (STM32_ETHERNET_BASE+STM32_ETH_DMARPDR_OFFSET)
+#define STM32_ETH_DMARDLAR (STM32_ETHERNET_BASE+STM32_ETH_DMARDLAR_OFFSET)
+#define STM32_ETH_DMATDLAR (STM32_ETHERNET_BASE+STM32_ETH_DMATDLAR_OFFSET)
+#define STM32_ETH_DMASR (STM32_ETHERNET_BASE+STM32_ETH_DMASR_OFFSET)
+#define STM32_ETH_DMAOMR (STM32_ETHERNET_BASE+STM32_ETH_DMAOMR_OFFSET)
+#define STM32_ETH_DMAIER (STM32_ETHERNET_BASE+STM32_ETH_DMAIER_OFFSET)
+#define STM32_ETH_DMAMFBOC (STM32_ETHERNET_BASE+STM32_ETH_DMAMFBOC_OFFSET)
+#define STM32_ETH_DMARSWTR (STM32_ETHERNET_BASE+STM32_ETH_DMARSWTR_OFFSET)
+#define STM32_ETH_DMACHTDR (STM32_ETHERNET_BASE+STM32_ETH_DMACHTDR_OFFSET)
+#define STM32_ETH_DMACHRDR (STM32_ETHERNET_BASE+STM32_ETH_DMACHRDR_OFFSET)
+#define STM32_ETH_DMACHTBAR (STM32_ETHERNET_BASE+STM32_ETH_DMACHTBAR_OFFSET)
+#define STM32_ETH_DMACHRBAR (STM32_ETHERNET_BASE+STM32_ETH_DMACHRBAR_OFFSET)
+
+/* Register Bit-Field Definitions *******************************************************************/
+/* MAC Registers */
+
+/* Ethernet MAC configuration register */
+
+#define ETH_MACCR_RE (1 << 2) /* Bit 2: Receiver enable */
+#define ETH_MACCR_TE (1 << 3) /* Bit 3: Transmitter enable */
+#define ETH_MACCR_DC (1 << 4) /* Bit 4: Deferral check */
+#define ETH_MACCR_BL_SHIFT (5) /* Bits 5-6: Back-off limit */
+#define ETH_MACCR_BL_MASK (3 << ETH_MACCR_BL_SHIFT)
+# define ETH_MACCR_BL_10 (0 << ETH_MACCR_BL_SHIFT) /* 00: k = min (n, 10) */
+# define ETH_MACCR_BL_8 (1 << ETH_MACCR_BL_SHIFT) /* 01: k = min (n, 8) */
+# define ETH_MACCR_BL_4 (2 << ETH_MACCR_BL_SHIFT) /* 10: k = min (n, 4) */
+# define ETH_MACCR_BL_1 (3 << ETH_MACCR_BL_SHIFT) /* 11: k = min (n, 1) */
+#define ETH_MACCR_APCS (1 << 7) /* Bit 7: Automatic pad/CRC stripping */
+#define ETH_MACCR_RD (1 << 9) /* Bit 9: Retry disable */
+#define ETH_MACCR_IPCO (1 << 10) /* Bit 10: IPv4 checksum offload */
+#define ETH_MACCR_DM (1 << 11) /* Bit 11: Duplex mode */
+#define ETH_MACCR_LM (1 << 12) /* Bit 12: Loopback mode */
+#define ETH_MACCR_ROD (1 << 13) /* Bit 13: Receive own disable */
+#define ETH_MACCR_FES (1 << 14) /* Bit 14: Fast Ethernet speed */
+#define ETH_MACCR_CSD (1 << 16) /* Bit 16: Carrier sense disable */
+#define ETH_MACCR_IFG_SHIFT (17) /* Bits 17-19: Interframe gap */
+#define ETH_MACCR_IFG_MASK (7 << ETH_MACCR_IFG_SHIFT)
+# define ETH_MACCR_IFG(n) ((12-((n) >> 3)) << ETH_MACCR_IFG_SHIFT) /* n bit times, n=40,48,..96 */
+#define ETH_MACCR_JD (1 << 22) /* Bit 22: Jabber disable */
+#define ETH_MACCR_WD (1 << 23) /* Bit 23: Watchdog disable */
+#define ETH_MACCR_CSTF (1 << 25) /* Bits 25: CRC stripping for Type frames */
+
+/* Ethernet MAC frame filter register */
+
+#define ETH_MACFFR_PM (1 << 0) /* Bit 0: Promiscuous mode */
+#define ETH_MACFFR_HU (1 << 1) /* Bit 1: Hash unicast */
+#define ETH_MACFFR_HM (1 << 2) /* Bit 2: Hash multicast */
+#define ETH_MACFFR_DAIF (1 << 3) /* Bit 3: Destination address inverse filtering */
+#define ETH_MACFFR_PAM (1 << 4) /* Bit 4: Pass all multicast */
+#define ETH_MACFFR_BFD (1 << 5) /* Bit 5: Broadcast frames disable */
+#define ETH_MACFFR_PCF_SHIFT (6) /* Bits 6-7: Pass control frames */
+#define ETH_MACFFR_PCF_MASK (3 << ETH_MACFFR_PCF_SHIFT)
+# define ETH_MACFFR_PCF_NONE (0 << ETH_MACFFR_PCF_SHIFT) /* Prevents all control frames */
+# define ETH_MACFFR_PCF_PAUSE (1 << ETH_MACFFR_PCF_SHIFT) /* Prevents all except Pause control frames */
+# define ETH_MACFFR_PCF_ALL (2 << ETH_MACFFR_PCF_SHIFT) /* Forwards all control frames */
+# define ETH_MACFFR_PCF_FILTER (3 << ETH_MACFFR_PCF_SHIFT) /* Forwards all that pass address filter */
+#define ETH_MACFFR_SAIF (1 << 8) /* Bit 8: Source address inverse filtering */
+#define ETH_MACFFR_SAF (1 << 9) /* Bit 9: Source address filter */
+#define ETH_MACFFR_HPF (1 << 10) /* Bit 10: Hash or perfect filter */
+#define ETH_MACFFR_RA (1 << 31) /* Bit 31: Receive all */
+
+/* Ethernet MAC hash table high/low registers (32-bit values) */
+
+/* Ethernet MAC MII address register */
+
+#define ETH_MACMIIAR_MB (1 << 0) /* Bit 0: MII busy */
+#define ETH_MACMIIAR_MW (1 << 1) /* Bit 1: MII write */
+#define ETH_MACMIIAR_CR_SHIFT (2) /* Bits 2-4: Clock range */
+#define ETH_MACMIIAR_CR_MASK (7 << ETH_MACMIIAR_CR_SHIFT)
+#if 0 /* Per the reference manual */
+# define ETH_MACMIIAR_CR_60_100 (0 << ETH_MACMIIAR_CR_SHIFT) /* 000 60-100 MHzHCLK/42 */
+# define ETH_MACMIIAR_CR_100_168 (1 << ETH_MACMIIAR_CR_SHIFT) /* 001 100-168 MHz HCLK/62 */
+# define ETH_MACMIIAR_CR_20_35 (2 << ETH_MACMIIAR_CR_SHIFT) /* 010 20-35 MHz HCLK/16 */
+# define ETH_MACMIIAR_CR_35_60 (3 << ETH_MACMIIAR_CR_SHIFT) /* 011 35-60 MHz HCLK/26 */
+#else /* Per the driver example */
+# define ETH_MACMIIAR_CR_60_100 (0 << ETH_MACMIIAR_CR_SHIFT) /* 000 60-100 MHz HCLK/42 */
+# define ETH_MACMIIAR_CR_100_150 (1 << ETH_MACMIIAR_CR_SHIFT) /* 001 100-150 MHz HCLK/62 */
+# define ETH_MACMIIAR_CR_20_35 (2 << ETH_MACMIIAR_CR_SHIFT) /* 010 20-35 MHz HCLK/16 */
+# define ETH_MACMIIAR_CR_35_60 (3 << ETH_MACMIIAR_CR_SHIFT) /* 011 35-60 MHz HCLK/26 */
+# define ETH_MACMIIAR_CR_150_168 (4 << ETH_MACMIIAR_CR_SHIFT) /* 100 150-168 MHz HCLK/102 */
+#endif
+#define ETH_MACMIIAR_MR_SHIFT (6) /* Bits 6-10: MII register */
+#define ETH_MACMIIAR_MR_MASK (31 << ETH_MACMIIAR_MR_SHIFT)
+#define ETH_MACMIIAR_PA_SHIFT (11) /* Bits 11-15: PHY address */
+#define ETH_MACMIIAR_PA_MASK (31 << ETH_MACMIIAR_PA_SHIFT)
+
+/* Ethernet MAC MII data register */
+
+#define ETH_MACMIIDR_MASK (0xffff)
+
+/* Ethernet MAC flow control register */
+
+#define ETH_MACFCR_FCB_BPA (1 << 0) /* Bit 0: Flow control busy/back pressure activate */
+#define ETH_MACFCR_TFCE (1 << 1) /* Bit 1: Transmit flow control enable */
+#define ETH_MACFCR_RFCE (1 << 2) /* Bit 2: Receive flow control enable */
+#define ETH_MACFCR_UPFD (1 << 3) /* Bit 3: Unicast pause frame detect */
+#define ETH_MACFCR_PLT_SHIFT (4) /* Bits 4-5: Pause low threshold */
+#define ETH_MACFCR_PLT_MASK (3 << ETH_MACFCR_PLT_SHIFT)
+# define ETH_MACFCR_PLT_M4 (0 << ETH_MACFCR_PLT_SHIFT) /* 00 Pause - 4 slot times */
+# define ETH_MACFCR_PLT_M28 (1 << ETH_MACFCR_PLT_SHIFT) /* 01 Pause - 28 slot times */
+# define ETH_MACFCR_PLT_M144 (2 << ETH_MACFCR_PLT_SHIFT) /* 10 Pause - 144 slot times */
+# define ETH_MACFCR_PLT_M256 (3 << ETH_MACFCR_PLT_SHIFT) /* 11 Pause -s 256 slot times */
+#define ETH_MACFCR_ZQPD (1 << 7) /* Bit 7: Zero-quanta pause disable */
+#define ETH_MACFCR_PT_SHIFT (16) /* Bits 16-31: Pause time */
+#define ETH_MACFCR_PT_MASK (0xffff << ETH_MACFCR_PT_SHIFT)
+
+/* Ethernet MAC VLAN tag register */
+
+#define ETH_MACVLANTR_VLANTI_SHIFT (0) /* Bits 0-15: VLAN tag identifier (for receive frames) */
+#define ETH_MACVLANTR_VLANTI_MASK (0xffff << ETH_MACVLANTR_VLANTI_SHIFT)
+#define ETH_MACVLANTR_VLANTC (1 << 16) /* Bit 16: 12-bit VLAN tag comparison */
+
+/* Ethernet MAC remote wakeup frame filter reg. Provides 32-bit access to remote
+ * remote wake-up filters.
+ */
+
+/* Ethernet MAC PMT control and status register */
+
+#define ETH_MACPMTCSR_PD (1 << 0) /* Bit 0: Power down */
+#define ETH_MACPMTCSR_MPE (1 << 1) /* Bit 1: Magic Packet enable */
+#define ETH_MACPMTCSR_WFE (1 << 2) /* Bit 2: Wakeup frame enable */
+#define ETH_MACPMTCSR_MPR (1 << 5) /* Bit 5: Magic packet received */
+#define ETH_MACPMTCSR_WFR (1 << 6) /* Bit 6: Wakeup frame received */
+#define ETH_MACPMTCSR_GU (1 << 9) /* Bit 9: Global unicast */
+
+/* Ethernet MAC debug register */
+
+#define ETH_MACDBGR_MMRPEA (1 << 0) /* Bit 0: MAC MII receive protocol engine active */
+#define ETH_MACDBGR_MSFRWCS_SHIFT (1) /* Bits 1-2: MAC small FIFO read / write controllers status */
+#define ETH_MACDBGR_MSFRWCS_MASK (3 << ETH_MACDBGR_MSFRWCS_SHIFT)
+#define ETH_MACDBGR_RFWRA (1 << 4) /* Bit 4: Rx FIFO write controller active */
+#define ETH_MACDBGR_RFRCS_SHIFT (5) /* Bits 5-6: Rx FIFO read controller status */
+#define ETH_MACDBGR_RFRCS_MASK (3 << ETH_MACDBGR_RFRCS_SHIFT)
+# define ETH_MACDBGR_RFRCS_IDLE (0 << ETH_MACDBGR_RFRCS_SHIFT) /* 00: IDLE state */
+# define ETH_MACDBGR_RFRCS_RFRAME (1 << ETH_MACDBGR_RFRCS_SHIFT) /* 01: Reading frame data */
+# define ETH_MACDBGR_RFRCS_RSTATUS (2 << ETH_MACDBGR_RFRCS_SHIFT) /* 10: Reading frame status (or time-stamp) */
+# define ETH_MACDBGR_RFRCS_FLUSHING (3 << ETH_MACDBGR_RFRCS_SHIFT) /* 11: Flushing the frame data and status */
+#define ETH_MACDBGR_RFFL_SHIFT (8) /* Bits 8-9: Rx FIFO fill level */
+#define ETH_MACDBGR_RFFL_MASK (3 << ETH_MACDBGR_RFFL_SHIFT)
+# define ETH_MACDBGR_RFFL_EMPTY (0 << ETH_MACDBGR_RFFL_SHIFT) /* 00: RxFIFO empty */
+# define ETH_MACDBGR_RFFL_DEACT (1 << ETH_MACDBGR_RFFL_SHIFT) /* 01: RxFIFO fill-level below flow-control de-activate threshold */
+# define ETH_MACDBGR_RFFL_ACTIV (2 << ETH_MACDBGR_RFFL_SHIFT) /* 10: RxFIFO fill-level above flow-control activate threshold */
+# define ETH_MACDBGR_RFFL_FULL (3 << ETH_MACDBGR_RFFL_SHIFT) /* 11: RxFIFO full */
+#define ETH_MACDBGR_MMTEA (1 << 16) /* Bit 16: MAC MII transmit engine active */
+#define ETH_MACDBGR_MTFCS_SHIFT (17) /* Bits 17-18: MAC transmit frame controller status */
+#define ETH_MACDBGR_MTFCS_MASK (3 << ETH_MACDBGR_MTFCS_SHIFT)
+# define ETH_MACDBGR_MTFCS_IDLE (0 << ETH_MACDBGR_MTFCS_SHIFT) /* 00: Idle */
+# define ETH_MACDBGR_MTFCS_WAITING (1 << ETH_MACDBGR_MTFCS_SHIFT) /* 01: Waiting for Status of previous frame or IFG/backoff period to be over */
+# define ETH_MACDBGR_MTFCS_PAUSE (2 << ETH_MACDBGR_MTFCS_SHIFT) /* 10: Generating and transmitting a Pause control frame */
+# define ETH_MACDBGR_MTFCS_FRAME (3 << ETH_MACDBGR_MTFCS_SHIFT) /* 11: Transferring input frame for transmission */
+#define ETH_MACDBGR_MTP (1 << 19) /* Bit 19: MAC transmitter in pause */
+#define ETH_MACDBGR_TFRS_SHIFT (20) /* Bits 20-21: Tx FIFO read status */
+#define ETH_MACDBGR_TFRS_MASK (3 << ETH_MACDBGR_TFRS_SHIFT)
+# define ETH_MACDBGR_TFRS_IDLE (0 << ETH_MACDBGR_TFRS_SHIFT) /* 00: Idle state */
+# define ETH_MACDBGR_TFRS_READ (1 << ETH_MACDBGR_TFRS_SHIFT) /* 01: Read state */
+# define ETH_MACDBGR_TFRS_WAITING (2 << ETH_MACDBGR_TFRS_SHIFT) /* 10: Waiting for TxStatus from MAC transmitter */
+# define ETH_MACDBGR_TFRS_WRITING (3 << ETH_MACDBGR_TFRS_SHIFT) /* 11: Writing the received TxStatus or flushing the TxFIFO */
+#define ETH_MACDBGR_TFWA (1 << 22) /* Bit 22: Tx FIFO write active */
+#define ETH_MACDBGR_TFNE (1 << 24) /* Bit 24: Tx FIFO not empty */
+#define ETH_MACDBGR_TFF (1 << 25) /* Bit 25: Tx FIFO full */
+
+/* Ethernet MAC interrupt status register */
+
+#define ETH_MACSR_PMTS (1 << 3) /* Bit 3: PMT status */
+#define ETH_MACSR_MMCS (1 << 4) /* Bit 4: MMC status */
+#define ETH_MACSR_MMCRS (1 << 5) /* Bit 5: MMC receive status */
+#define ETH_MACSR_MMCTS (1 << 6) /* Bit 6: MMC transmit status */
+#define ETH_MACSR_TSTS (1 << 9) /* Bit 9: Time stamp trigger status */
+
+/* Ethernet MAC interrupt mask register */
+
+#define ETH_MACIMR_PMTIM (1 << 3) /* Bit 3: PMT interrupt mask */
+#define ETH_MACIMR_TSTIM (1 << 9) /* Bit 9: Time stamp trigger interrupt mask */
+#define ETH_MACIMR_ALLINTS (ETH_MACIMR_PMTIM|ETH_MACIMR_TSTIM)
+
+/* Ethernet MAC address 0 high register */
+
+#define ETH_MACA0HR_MACA0H_SHIFT (0) /* Bits 0-15: MAC address0 high [47:32] */
+#define ETH_MACA0HR_MACA0H_MASK (0xffff << ETH_MACA0HR_MACA0H_SHIFT)
+#define ETH_MACA0HR_MO (1 << 31) /* Bit 31:Always */
+
+/* Ethernet MAC address 0 low register (MAC address0 low [31:0]) */
+
+/* Ethernet MAC address 1 high register */
+
+#define ETH_MACA1HR_MACA1H_SHIFT (0) /* Bits 0-15: MAC address1 high [47:32] */
+#define ETH_MACA1HR_MACA1H_MASK (0xffff << ETH_MACA1HR_MACA1H_SHIFT)
+#define ETH_MACA1HR_MBC_SHIFT (24) /* Bits 24-29: Mask byte control */
+#define ETH_MACA1HR_MBC_MASK (0x3f << ETH_MACA1HR_MBC_SHIFT)
+# define ETH_MACA1HR_MBC_40_47 (0x20 << ETH_MACA1HR_MBC_SHIFT) /* Bit 29: ETH_MACA1HR [8-15] */
+# define ETH_MACA1HR_MBC_32_39 (0x10 << ETH_MACA1HR_MBC_SHIFT) /* Bit 28: ETH_MACA1HR [0-7] */
+# define ETH_MACA1HR_MBC_24_31 (0x08 << ETH_MACA1HR_MBC_SHIFT) /* Bit 27: ETH_MACA1LR [24-31] */
+# define ETH_MACA1HR_MBC_16_23 (0x04 << ETH_MACA1HR_MBC_SHIFT) /* Bit 26: ETH_MACA1LR [16-23] */
+# define ETH_MACA1HR_MBC_8_15 (0x02 << ETH_MACA1HR_MBC_SHIFT) /* Bit 25: ETH_MACA1LR [8-15] */
+# define ETH_MACA1HR_MBC_0_7 (0x01 << ETH_MACA1HR_MBC_SHIFT) /* Bit 24: ETH_MACA1LR [0-7] */
+#define ETH_MACA1HR_SA (1 << 30) /* Bit 30: Source address */
+#define ETH_MACA1HR_AE (1 << 31) /* Bit 31: Address enable */
+
+/* Ethernet MAC address1 low register (MAC address1 low [31:0]) */
+
+/* Ethernet MAC address 2 high register */
+
+#define ETH_MACA2HR_MACA2H_SHIFT (0) /* Bits 0-15: MAC address2 high [47:32] */
+#define ETH_MACA2HR_MACA2H_MASK (0xffff << ETH_MACA2HR_MACA2H_SHIFT)
+#define ETH_MACA2HR_MBC_SHIFT (24) /* Bits 24-29: Mask byte control */
+#define ETH_MACA2HR_MBC_MASK (0x3f << ETH_MACA2HR_MBC_SHIFT)
+# define ETH_MACA2HR_MBC_40_47 (0x20 << ETH_MACA2HR_MBC_SHIFT) /* Bit 29: ETH_MACA2HR [8-15] */
+# define ETH_MACA2HR_MBC_32_39 (0x10 << ETH_MACA2HR_MBC_SHIFT) /* Bit 28: ETH_MACA2HR [0-7] */
+# define ETH_MACA2HR_MBC_24_31 (0x08 << ETH_MACA2HR_MBC_SHIFT) /* Bit 27: ETH_MACA2LR [24-31] */
+# define ETH_MACA2HR_MBC_16_23 (0x04 << ETH_MACA2HR_MBC_SHIFT) /* Bit 26: ETH_MACA2LR [16-23] */
+# define ETH_MACA2HR_MBC_8_15 (0x02 << ETH_MACA2HR_MBC_SHIFT) /* Bit 25: ETH_MACA2LR [8-15] */
+# define ETH_MACA2HR_MBC_0_7 (0x01 << ETH_MACA2HR_MBC_SHIFT) /* Bit 24: ETH_MACA2LR [0-7] */
+#define ETH_MACA2HR_SA (1 << 30) /* Bit 30: Source address */
+#define ETH_MACA2HR_AE (1 << 31) /* Bit 31: Address enable */
+
+/* Ethernet MAC address 2 low register (MAC address2 low [31:0]) */
+
+/* Ethernet MAC address 3 high register */
+
+#define ETH_MACA3HR_MACA3H_SHIFT (0) /* Bits 0-15: MAC address3 high [47:32] */
+#define ETH_MACA3HR_MACA3H_MASK (0xffff << ETH_MACA3HR_MACA3H_SHIFT)
+#define ETH_MACA3HR_MBC_SHIFT (24) /* Bits 24-29: Mask byte control */
+#define ETH_MACA3HR_MBC_MASK (0x3f << ETH_MACA3HR_MBC_SHIFT)
+# define ETH_MACA3HR_MBC_40_47 (0x20 << ETH_MACA3HR_MBC_SHIFT) /* Bit 29: ETH_MACA3HR [8-15] */
+# define ETH_MACA3HR_MBC_32_39 (0x10 << ETH_MACA3HR_MBC_SHIFT) /* Bit 28: ETH_MACA3HR [0-7] */
+# define ETH_MACA3HR_MBC_24_31 (0x08 << ETH_MACA3HR_MBC_SHIFT) /* Bit 27: ETH_MACA3LR [24-31] */
+# define ETH_MACA3HR_MBC_16_23 (0x04 << ETH_MACA3HR_MBC_SHIFT) /* Bit 26: ETH_MACA3LR [16-23] */
+# define ETH_MACA3HR_MBC_8_15 (0x02 << ETH_MACA3HR_MBC_SHIFT) /* Bit 25: ETH_MACA3LR [8-15] */
+# define ETH_MACA3HR_MBC_0_7 (0x01 << ETH_MACA3HR_MBC_SHIFT) /* Bit 24: ETH_MACA3LR [0-7] */
+#define ETH_MACA3HR_SA (1 << 30) /* Bit 30: Source address */
+#define ETH_MACA3HR_AE (1 << 31) /* Bit 31: Address enable */
+
+/* Ethernet MAC address 3 low register (MAC address3 low [31:0]) */
+
+/* MMC Registers */
+
+/* Ethernet MMC control register */
+
+#define ETH_MMCCR_CR (1 << 0) /* Bit 0: Counter reset */
+#define ETH_MMCCR_CSR (1 << 1) /* Bit 1: Counter stop rollover */
+#define ETH_MMCCR_ROR (1 << 2) /* Bit 2: Reset on read */
+#define ETH_MMCCR_MCF (1 << 3) /* Bit 3: MMC counter freeze */
+#define ETH_MMCCR_MCP (1 << 4) /* Bit 4: MMC counter preset */
+#define ETH_MMCCR_MCFHP (1 << 5) /* Bit 5: MMC counter Full-Half preset */
+
+/* Ethernet MMC receive interrupt and interrupt mask registers */
+
+#define ETH_MMCRI_RFCE (1 << 5) /* Bit 5: Received frame CRC error */
+#define ETH_MMCRI_RFAE (1 << 6) /* Bit 6: Received frames alignment error */
+#define ETH_MMCRI_RGUF (1 << 17) /* Bit 17: Received good unicast frames */
+
+/* Ethernet MMC transmit interrupt and interrupt mask register */
+
+#define ETH_MMCTI_TGFSC (1 << 14) /* Bit 14: Transmitted good frames single collision */
+#define ETH_MMCTI_TGFMSC (1 << 15) /* Bit 15: Transmitted good frames more single collision */
+#define ETH_MMCTI_TGF (1 << 21) /* Bit 21: Transmitted good frames */
+
+/* 32-bit counters:
+ *
+ * Ethernet MMC transmitted good frames counter register (single collision)
+ * Ethernet MMC transmitted good frames counter register (multiple-collision)
+ * Ethernet MMC transmitted good frames counter register
+ * Ethernet MMC received frames with CRC error counter register
+ * Ethernet MMC received frames with alignment error counter
+ * MMC received good unicast frames counter register
+ */
+
+/* IEEE 1588 time stamp registers */
+
+/* Ethernet PTP time stamp control register */
+
+#define ETH_PTPTSCR_TSE (1 << 0) /* Bit 0: Time stamp enable */
+#define ETH_PTPTSCR_TSFCU (1 << 1) /* Bit 1: Time stamp fine or coarse update */
+#define ETH_PTPTSCR_TSSTI (1 << 2) /* Bit 2: Time stamp system time initialize */
+#define ETH_PTPTSCR_TSSTU (1 << 3) /* Bit 3: Time stamp system time update */
+#define ETH_PTPTSCR_TSITE (1 << 4) /* Bit 4: Time stamp interrupt trigger enable */
+#define ETH_PTPTSCR_TSARU (1 << 5) /* Bit 5: Time stamp addend register update */
+#define ETH_PTPTSCR_TSSARFE (1 << 8) /* Bit 8: Time stamp snapshot for all received frames enable */
+#define ETH_PTPTSCR_TSSSR (1 << 9) /* Bit 9: Time stamp subsecond rollover: digital or binary rollover control */
+#define ETH_PTPTSCR_TSPTPPSV2E (1 << 10) /* Bit 10: Time stamp PTP packet snooping for version2 format enable */
+#define ETH_PTPTSCR_TSSPTPOEFE (1 << 11) /* Bit 11: Time stamp snapshot for PTP over ethernet frames enable */
+#define ETH_PTPTSCR_TSSIPV6FE (1 << 12) /* Bit 12: Time stamp snapshot for IPv6 frames enable */
+#define ETH_PTPTSCR_TSSIPV4FE (1 << 13) /* Bit 13: Time stamp snapshot for IPv4 frames enable */
+#define ETH_PTPTSCR_TSSEME (1 << 14) /* Bit 14: Time stamp snapshot for event message enable */
+#define ETH_PTPTSCR_TSSMRME (1 << 15) /* Bit 15: Time stamp snapshot for message relevant to master enable */
+#define ETH_PTPTSCR_TSCNT_SHIFT (16) /* Bits 16-17: Time stamp clock node type */
+#define ETH_PTPTSCR_TSCNT_MASK (3 << ETH_PTPTSCR_TSCNT_SHIFT)
+# define ETH_PTPTSCR_TSCNT_ORDINARY (0 << ETH_PTPTSCR_TSCNT_SHIFT) /* 00: Ordinary clock */
+# define ETH_PTPTSCR_TSCNT_BOUNDARY (1 << ETH_PTPTSCR_TSCNT_SHIFT) /* 01: Boundary clock */
+# define ETH_PTPTSCR_TSCNT_E2E (2 << ETH_PTPTSCR_TSCNT_SHIFT) /* 10: End-to-end transparent clock */
+# define ETH_PTPTSCR_TSCNT_P2P (3 << ETH_PTPTSCR_TSCNT_SHIFT) /* 11: Peer-to-peer transparent clock */
+#define ETH_PTPTSCR_TSPFFMAE (1 << 18) /* Bit 18: Time stamp PTP frame filtering MAC address enable */
+
+/* Ethernet PTP subsecond increment register */
+
+#define ETH_PTPSSIR_MASK (0xff)
+
+/* Ethernet PTP time stamp high register (32-bit) */
+
+/* Ethernet PTP time stamp low register */
+
+#define ETH_PTPTSLR_STPNS (1 << 31) /* Bit 31: System time positive or negative sign */
+#define ETH_PTPTSLR_MASK (0x7fffffff) /* Bits 0-30: System time subseconds */
+
+/* Ethernet PTP time stamp high update register (32-bit) */
+
+/* Ethernet PTP time stamp low update register */
+
+#define ETH_PTPTSLU_TSUPNS (1 << 31) /* Bit 31: System time positive or negative sign */
+#define ETH_PTPTSLU_MASK (0x7fffffff) /* Bits 0-30: Time stamp update subsecond */
+
+/* Ethernet PTP time stamp addend register (32-bit) */
+/* Ethernet PTP target time high register (32-bit) */
+/* Ethernet PTP target time low register (32-bit) */
+
+/* Ethernet PTP time stamp status register */
+
+#define ETH_PTPTSSR_TSSO (1 << 0) /* Bit 0: Time stamp second overflow */
+#define ETH_PTPTSSR_TSTTR (1 << 1) /* Bit 1: Time stamp target time reached */
+
+/* Ethernet PTP PPS control register */
+
+#define ETH_PTPPPSCR_PPSFREQ_SHIFT (0) /* Bits 0-3: PPS frequency selection */
+#define ETH_PTPPPSCR_PPSFREQ_MASK (15 << ETH_PTPPPSCR_PPSFREQ_SHIFT)
+# define ETH_PTPPPSCR_PPSFREQ_1HZ (0 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 1 Hz with pulse width of 125/100 ms for binary/digital rollover */
+# define ETH_PTPPPSCR_PPSFREQ_2HZ (1 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 2 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_4HZ (2 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 4 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_8HZ (3 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 8 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_16HZ (4 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 16 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_32HZ (5 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 32 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_64HZ (6 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 64 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_128HZ (7 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 128 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_256HZ (8 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 256 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_512HZ (9 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 512 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_1KHZ (10 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 1024 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_2KHZ (11 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 2048 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_4KHZ (12 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 4096 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_8KHZ (13 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 8192 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_16KHZ (14 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 16384 Hz with 50% duty cycle */
+# define ETH_PTPPPSCR_PPSFREQ_32KHZ (15 << ETH_PTPPPSCR_PPSFREQ_SHIFT) /* 32768 Hz with 50% duty cycle */
+
+/* DMA Registers */
+
+/* Ethernet DMA bus mode register */
+
+#define ETH_DMABMR_SR (1 << 0) /* Bit 0: Software reset */
+#define ETH_DMABMR_DA (1 << 1) /* Bit 1: DMA Arbitration */
+#define ETH_DMABMR_DSL_SHIFT (2) /* Bits 2-6: Descriptor skip length */
+#define ETH_DMABMR_DSL_MASK (31 << ETH_DMABMR_DSL_SHIFT)
+# define ETH_DMABMR_DSL(n) ((n) << ETH_DMABMR_DSL_SHIFT)
+#define ETH_DMABMR_EDFE (1 << 7) /* Bit 7: Enhanced descriptor format enable */
+#define ETH_DMABMR_PBL_SHIFT (8) /* Bits 8-13: Programmable burst length */
+# define ETH_DMABMR_PBL(n) ((n) << ETH_DMABMR_PBL_SHIFT) /* n=1, 2, 4, 8, 16, 32 */
+#define ETH_DMABMR_PBL_MASK (0x3f << ETH_DMABMR_PBL_SHIFT)
+#define ETH_DMABMR_RTPR_SHIFT (14) /* Bits 14-15: Rx Tx priority ratio */
+#define ETH_DMABMR_RTPR_MASK (3 << ETH_DMABMR_RTPR_SHIFT)
+# define ETH_DMABMR_RTPR_1TO1 (0 << ETH_DMABMR_RTPR_SHIFT) /* 00: 1:1 */
+# define ETH_DMABMR_RTPR_2TO1 (1 << ETH_DMABMR_RTPR_SHIFT) /* 01: 2:1 */
+# define ETH_DMABMR_RTPR_3TO1 (2 << ETH_DMABMR_RTPR_SHIFT) /* 10: 3:1 */
+# define ETH_DMABMR_RTPR_4TO1 (3 << ETH_DMABMR_RTPR_SHIFT) /* 11: 4:1 */
+#define ETH_DMABMR_FB (1 << 16) /* Bit 16: Fixed burst */
+#define ETH_DMABMR_RDP_SHIFT (17) /* Bits 17-22: Rx DMA PBL */
+#define ETH_DMABMR_RDP_MASK (0x3f << ETH_DMABMR_RDP_SHIFT)
+# define ETH_DMABMR_RDP(n) ((n) << ETH_DMABMR_RDP_SHIFT) /* n=1, 2, 4, 8, 16, 32 */
+#define ETH_DMABMR_USP (1 << 23) /* Bit 23: Use separate PBL */
+#define ETH_DMABMR_FPM (1 << 24) /* Bit 24: 4xPBL mode */
+#define ETH_DMABMR_AAB (1 << 25) /* Bit 25: Address-aligned beats */
+#define ETH_DMABMR_MB (1 << 26) /* Bit 26: Mixed burst */
+
+/* Ethernet DMA transmit poll demand register (32-bit) */
+/* Ethernet DMA receive poll demand register (32-bit) */
+/* Ethernet DMA receive descriptor list address register (32-bit address) */
+/* Ethernet DMA transmit descriptor list address register (32-bit address) */
+
+/* Interrupt bit definitions common between the DMA status register (DMASR) and
+ * the DMA interrupt enable register (DMAIER).
+ */
+
+#define ETH_DMAINT_TI (1 << 0) /* Bit 0: Transmit interrupt */
+#define ETH_DMAINT_TPSI (1 << 1) /* Bit 1: Transmit process stopped interrupt */
+#define ETH_DMAINT_TBUI (1 << 2) /* Bit 2: Transmit buffer unavailable interrupt */
+#define ETH_DMAINT_TJTI (1 << 3) /* Bit 3: Transmit jabber timeout interrupt */
+#define ETH_DMAINT_ROI (1 << 4) /* Bit 4: Overflow interrupt */
+#define ETH_DMAINT_TUI (1 << 5) /* Bit 5: Underflow interrupt */
+#define ETH_DMAINT_RI (1 << 6) /* Bit 6: Receive interrupt */
+#define ETH_DMAINT_RBUI (1 << 7) /* Bit 7: Receive buffer unavailable interrupt */
+#define ETH_DMAINT_RPSI (1 << 8) /* Bit 8: Receive process stopped interrupt */
+#define ETH_DMAINT_RWTI (1 << 9) /* Bit 9: Receive watchdog timeout interrupt */
+#define ETH_DMAINT_ETI (1 << 10) /* Bit 10: Early transmit interrupt */
+#define ETH_DMAINT_FBEI (1 << 13) /* Bit 13: Fatal bus error interrupt */
+#define ETH_DMAINT_ERI (1 << 14) /* Bit 14: Early receive interrupt */
+#define ETH_DMAINT_AIS (1 << 15) /* Bit 15: Abnormal interrupt summary */
+#define ETH_DMAINT_NIS (1 << 16) /* Bit 16: Normal interrupt summary */
+
+/* Ethernet DMA status register (in addition to the interrupt bits above */
+
+#define ETH_DMASR_RPS_SHIFT (17) /* Bits 17-19: Receive process state */
+#define ETH_DMASR_RPS_MASK (7 << ETH_DMASR_RPS_SHIFT)
+# define ETH_DMASR_RPS_STOPPED (0 << ETH_DMASR_RPS_SHIFT) /* 000: Stopped: Reset or Stop Receive Command issued */
+# define ETH_DMASR_RPS_RXDESC (1 << ETH_DMASR_RPS_SHIFT) /* 001: Running: Fetching receive transfer descriptor */
+# define ETH_DMASR_RPS_WAITING (3 << ETH_DMASR_RPS_SHIFT) /* 011: Running: Waiting for receive packet */
+# define ETH_DMASR_RPS_SUSPENDED (4 << ETH_DMASR_RPS_SHIFT) /* 100: Suspended: Receive descriptor unavailable */
+# define ETH_DMASR_RPS_CLOSING (5 << ETH_DMASR_RPS_SHIFT) /* 101: Running: Closing receive descriptor */
+# define ETH_DMASR_RPS_TRANSFER (6 << ETH_DMASR_RPS_SHIFT) /* 111: Running: Transferring the receive data to memory */
+#define ETH_DMASR_TPS_SHIFT (20) /* Bits 20-22: Transmit process state */
+#define ETH_DMASR_TPS_MASK (7 << ETH_DMASR_TPS_SHIFT)
+# define ETH_DMASR_TPS_STOPPED (0 << ETH_DMASR_TPS_SHIFT) /* 000: Stopped; Reset or Stop Transmit Command issued */
+# define ETH_DMASR_TPS_TXDESC (1 << ETH_DMASR_TPS_SHIFT) /* 001: Running; Fetching transmit transfer descriptor */
+# define ETH_DMASR_TPS_WAITING (2 << ETH_DMASR_TPS_SHIFT) /* 010: Running; Waiting for status */
+# define ETH_DMASR_TPS_TRANSFER (3 << ETH_DMASR_TPS_SHIFT) /* 011: Running; Reading data and queuing to transmit (TxFIFO) */
+# define ETH_DMASR_TPS_SUSPENDED (6 << ETH_DMASR_TPS_SHIFT) /* 110: Suspended; Transmit descriptor unavailable or buffer underflow */
+# define ETH_DMASR_TPS_CLOSING (7 << ETH_DMASR_TPS_SHIFT) /* 111: Running; Closing transmit descriptor */
+#define ETH_DMASR_EBS_SHIFT (23) /* Bits 23-25: Error bits status */
+#define ETH_DMASR_EBS_MASK (7 << ETH_DMASR_EBS_SHIFT)
+#define ETH_DMASR_EBS_TXDMS (1 << ETH_DMASR_EBS_SHIFT) /* Bit 23 1 Error during data transfer by TxDMA */
+#define ETH_DMASR_EBS_READ (2 << ETH_DMASR_EBS_SHIFT) /* Bit 24 1 Error during read transfer */
+#define ETH_DMASR_EBS_DESC (4 << ETH_DMASR_EBS_SHIFT) /* Bit 25 1 Error during descriptor access */
+#define ETH_DMASR_MMCS (1 << 27) /* Bit 27: MMC status */
+#define ETH_DMASR_PMTS (1 << 28) /* Bit 28: PMT status */
+#define ETH_DMASR_TSTS (1 << 29) /* Bit 29: Time stamp trigger status */
+
+/* Ethernet DMA operation mode register */
+
+#define ETH_DMAOMR_SR (1 << 1) /* Bit 1: Start/stop receive */
+#define ETH_DMAOMR_OSF (1 << 2) /* Bit 2: Operate on second frame */
+#define ETH_DMAOMR_RTC_SHIFT (3) /* Bits 3-4: Receive threshold control */
+#define ETH_DMAOMR_RTC_MASK (3 << ETH_DMAOMR_RTC_SHIFT)
+# define ETH_DMAOMR_RTC_64 (0 << ETH_DMAOMR_RTC_SHIFT)
+# define ETH_DMAOMR_RTC_32 (1 << ETH_DMAOMR_RTC_SHIFT)
+# define ETH_DMAOMR_RTC_96 (2 << ETH_DMAOMR_RTC_SHIFT)
+# define ETH_DMAOMR_RTC_128 (3 << ETH_DMAOMR_RTC_SHIFT)
+#define ETH_DMAOMR_FUGF (1 << 6) /* Bit 6: Forward undersized good frames */
+#define ETH_DMAOMR_FEF (1 << 7) /* Bit 7: Forward error frames */
+#define ETH_DMAOMR_ST (1 << 13) /* Bit 13: Start/stop transmission */
+#define ETH_DMAOMR_TTC_SHIFT (14) /* Bits 14-16: Transmit threshold control */
+#define ETH_DMAOMR_TTC_MASK (7 << ETH_DMAOMR_TTC_SHIFT)
+# define ETH_DMAOMR_TTC_64 (0 << ETH_DMAOMR_TTC_SHIFT)
+# define ETH_DMAOMR_TTC_128 (1 << ETH_DMAOMR_TTC_SHIFT)
+# define ETH_DMAOMR_TTC_192 (2 << ETH_DMAOMR_TTC_SHIFT)
+# define ETH_DMAOMR_TTC_256 (3 << ETH_DMAOMR_TTC_SHIFT)
+# define ETH_DMAOMR_TTC_40 (4 << ETH_DMAOMR_TTC_SHIFT)
+# define ETH_DMAOMR_TTC_32 (5 << ETH_DMAOMR_TTC_SHIFT)
+# define ETH_DMAOMR_TTC_24 (6 << ETH_DMAOMR_TTC_SHIFT)
+# define ETH_DMAOMR_TTC_16 (7 << ETH_DMAOMR_TTC_SHIFT)
+#define ETH_DMAOMR_FTF (1 << 20) /* Bit 20: Flush transmit FIFO */
+#define ETH_DMAOMR_TSF (1 << 21) /* Bit 21: Transmit store and forward */
+#define ETH_DMAOMR_DFRF (1 << 24) /* Bit 24: Disable flushing of received frames */
+#define ETH_DMAOMR_RSF (1 << 25) /* Bit 25: Receive store and forward */
+#define ETH_DMAOMR_DTCEFD (1 << 26) /* Bit 26: Dropping of TCP/IP checksum error frames disable */
+
+/* Ethernet DMA missed frame and buffer overflow counter register */
+
+#define ETH_DMAMFBOC_MFC_SHIFT (0) /* Bits 0-15: Missed frames by the controller */
+#define ETH_DMAMFBOC_MFC_MASK (0xffff << ETH_DMAMFBOC_MFC_SHIFT)
+#define ETH_DMAMFBOC_OMFC (1 << 16) /* Bit 16: Overflow bit for missed frame counter */
+#define ETH_DMAMFBOC_MFA_SHIFT (17) /* Bits 17-27: Missed frames by the application */
+#define ETH_DMAMFBOC_MFA_MASK (0x7ff << ETH_DMAMFBOC_MFA_SHIFT)
+#define ETH_DMAMFBOC_OFOC (1 << 28) /* Bit 28: Overflow bit for FIFO overflow counter */
+
+/* Ethernet DMA receive status watchdog timer register */
+
+#define ETH_DMARSWTR_MASK (0xff)
+
+/* Ethernet DMA current host transmit descriptor register (32-bit address) */
+/* Ethernet DMA current host receive descriptor register (32-bit address) */
+/* Ethernet DMA current host transmit buffer address register (32-bit address) */
+/* Ethernet DMA current host receive buffer address register (32-bit address) */
+
+/* DMA Descriptors **********************************************************************************/
+/* TDES0: Transmit descriptor Word0 */
+
+#define ETH_TDES0_DB (1 << 0) /* Bit 0: Deferred bit */
+#define ETH_TDES0_UF (1 << 1) /* Bit 1: Underflow error */
+#define ETH_TDES0_ED (1 << 2) /* Bit 2: Excessive deferral */
+#define ETH_TDES0_CC_SHIFT (3) /* Bits 3-6: Collision count */
+#define ETH_TDES0_CC_MASK (15 << ETH_TDES0_CC_SHIFT)
+#define ETH_TDES0_VF (1 << 7) /* Bit 7: VLAN frame */
+#define ETH_TDES0_EC (1 << 8) /* Bit 8: Excessive collision */
+#define ETH_TDES0_LCO (1 << 9) /* Bit 9: Late collision */
+#define ETH_TDES0_NC (1 << 10) /* Bit 10: No carrier */
+#define ETH_TDES0_LCA (1 << 11) /* Bit 11: Loss of carrier */
+#define ETH_TDES0_IPE (1 << 12) /* Bit 12: IP payload error */
+#define ETH_TDES0_FF (1 << 13) /* Bit 13: Frame flushed */
+#define ETH_TDES0_JT (1 << 14) /* Bit 14: Jabber timeout */
+#define ETH_TDES0_ES (1 << 15) /* Bit 15: Error summary */
+#define ETH_TDES0_IHE (1 << 16) /* Bit 16: IP header error */
+#define ETH_TDES0_TTSS (1 << 17) /* Bit 17: Transmit time stamp status */
+#define ETH_TDES0_TCH (1 << 20) /* Bit 20: Second address chained */
+#define ETH_TDES0_TER (1 << 21) /* Bit 21: Transmit end of ring */
+#define ETH_TDES0_CIC_SHIFT (22) /* Bits 22-23: Checksum insertion control */
+#define ETH_TDES0_CIC_MASK (3 << ETH_TDES0_CIC_SHIFT)
+# define ETH_TDES0_CIC_DISABLED (0 << ETH_TDES0_CIC_SHIFT) /* Checksum disabled */
+# define ETH_TDES0_CIC_IH (1 << ETH_TDES0_CIC_SHIFT) /* IP header checksum enabled */
+# define ETH_TDES0_CIC_IHPL (2 << ETH_TDES0_CIC_SHIFT) /* IP header and payload checksum enabled */
+# define ETH_TDES0_CIC_ALL (3 << ETH_TDES0_CIC_SHIFT) /* IP Header, payload, and pseudo-header checksum enabled */
+#define ETH_TDES0_TTSE (1 << 25) /* Bit 25: Transmit time stamp enable */
+#define ETH_TDES0_DP (1 << 26) /* Bit 26: Disable pad */
+#define ETH_TDES0_DC (1 << 27) /* Bit 27: Disable CRC */
+#define ETH_TDES0_FS (1 << 28) /* Bit 28: First segment */
+#define ETH_TDES0_LS (1 << 29) /* Bit 29: Last segment */
+#define ETH_TDES0_IC (1 << 30) /* Bit 30: Interrupt on completion */
+#define ETH_TDES0_OWN (1 << 31) /* Bit 31: Own bit */
+
+/* TDES1: Transmit descriptor Word1 */
+
+#define ETH_TDES1_TBS1_SHIFT (0) /* Bits 0-12: Transmit buffer 1 size */
+#define ETH_TDES1_TBS1_MASK (0x1fff << ETH_TDES1_TBS1_SHIFT)
+#define ETH_TDES1_TBS2_SHIFT (16) /* Bits 16-28: Transmit buffer 2 size */
+#define ETH_TDES1_TBS2_MASK (0x1fff << ETH_TDES1_TBS2_SHIFT)
+
+/* TDES2: Transmit descriptor Word2 (32-bit address) */
+/* TDES3: Transmit descriptor Word3 (32-bit address) */
+/* TDES6: Transmit descriptor Word6 (32-bit time stamp) */
+/* TDES7: Transmit descriptor Word7 (32-bit time stamp) */
+
+/* RDES0: Receive descriptor Word0 */
+
+#define ETH_RDES0_PCE (1 << 0) /* Bit 0: Payload checksum error */
+#define ETH_RDES0_ESA (1 << 0) /* Bit 0: Extended status available */
+#define ETH_RDES0_CE (1 << 1) /* Bit 1: CRC error */
+#define ETH_RDES0_DBE (1 << 2) /* Bit 2: Dribble bit error */
+#define ETH_RDES0_RE (1 << 3) /* Bit 3: Receive error */
+#define ETH_RDES0_RWT (1 << 4) /* Bit 4: Receive watchdog timeout */
+#define ETH_RDES0_FT (1 << 5) /* Bit 5: Frame type */
+#define ETH_RDES0_LCO (1 << 6) /* Bit 6: Late collision */
+#define ETH_RDES0_TSV (1 << 7) /* Bit 7: Time stamp valid */
+#define ETH_RDES0_IPHCE (1 << 7) /* Bit 7: IPv header checksum error */
+#define ETH_RDES0_LS (1 << 8) /* Bit 8: Last descriptor */
+#define ETH_RDES0_FS (1 << 9) /* Bit 9: First descriptor */
+#define ETH_RDES0_VLAN (1 << 10) /* Bit 10: VLAN tag */
+#define ETH_RDES0_OE (1 << 11) /* Bit 11: Overflow error */
+#define ETH_RDES0_LE (1 << 12) /* Bit 12: Length error */
+#define ETH_RDES0_SAF (1 << 13) /* Bit 13: Source address filter fail */
+#define ETH_RDES0_DE (1 << 14) /* Bit 14: Descriptor error */
+#define ETH_RDES0_ES (1 << 15) /* Bit 15: Error summary */
+#define ETH_RDES0_FL_SHIFT (16) /* Bits 16-29: Frame length */
+#define ETH_RDES0_FL_MASK (0x3fff << ETH_RDES0_FL_SHIFT)
+#define ETH_RDES0_AFM (1 << 30) /* Bit 30: Destination address filter fail */
+#define ETH_RDES0_OWN (1 << 31) /* Bit 31: Own bit */
+
+/* RDES1: Receive descriptor Word1 */
+
+#define ETH_RDES1_RBS1_SHIFT (0) /* Bits 0-12: Receive buffer 1 size */
+#define ETH_RDES1_RBS1_MASK (0x1fff << ETH_RDES1_RBS1_SHIFT)
+#define ETH_RDES1_RCH (1 << 14) /* Bit 14: Second address chained */
+#define ETH_RDES1_RER (1 << 15) /* Bit 15: Receive end of ring */
+#define ETH_RDES1_RBS2_SHIFT (16) /* Bits 16-28: Receive buffer 2 size */
+#define ETH_RDES1_RBS2_MASK (0x1fff << ETH_RDES1_RBS2_SHIFT)
+#define ETH_RDES1_DIC (1 << 31) /* Bit 31: Disable interrupt on completion */
+
+/* RDES2: Receive descriptor Word2 (32-bit address) */
+/* RDES3: Receive descriptor Word3 (32-bit address) */
+
+/* RDES4: Receive descriptor Word4 */
+
+#define ETH_RDES4_IPPT_SHIFT (0) /* Bits 0-2: IP payload type */
+#define ETH_RDES4_IPPT_MASK (7 << ETH_RDES4_IPPT_SHIFT)
+# define ETH_RDES4_IPPT_UDP (1 << ETH_RDES4_IPPT_SHIFT) /* UDP payload in IP datagram */
+# define ETH_RDES4_IPPT_TCP (2 << ETH_RDES4_IPPT_SHIFT) /* TCP payload in IP datagram */
+# define ETH_RDES4_IPPT_ICMP (3 << ETH_RDES4_IPPT_SHIFT) /* ICMP payload in IP datagram */
+#define ETH_RDES4_IPHE (1 << 3) /* Bit 3: IP header error */
+#define ETH_RDES4_IPPE (1 << 4) /* Bit 4: IP payload error */
+#define ETH_RDES4_IPCB (1 << 5) /* Bit 5: IP checksum bypassed */
+#define ETH_RDES4_IPV4PR (1 << 6) /* Bit 6: IPv4 packet received */
+#define ETH_RDES4_IPV6PR (1 << 7) /* Bit 7: IPv6 packet received */
+#define ETH_RDES4_PMT_SHIFT (8) /* Bits 8-11: PTP message type */
+#define ETH_RDES4_PMT_MASK (15 << ETH_RDES4_PMT_SHIFT)
+# define ETH_RDES4_PMT_NONE (0 << ETH_RDES4_PMT_SHIFT) /* No PTP message received */
+# define ETH_RDES4_PMT_SYNC (1 << ETH_RDES4_PMT_SHIFT) /* SYNC (all clock types) */
+# define ETH_RDES4_PMT_FOLLOWUP (2 << ETH_RDES4_PMT_SHIFT) /* Follow_Up (all clock types) */
+# define ETH_RDES4_PMT_DELAYREQ (3 << ETH_RDES4_PMT_SHIFT) /* Delay_Req (all clock types) */
+# define ETH_RDES4_PMT_DELAYRESP (4 << ETH_RDES4_PMT_SHIFT) /* Delay_Resp (all clock types) */
+# define ETH_RDES4_PMT_PDELREQAM (5 << ETH_RDES4_PMT_SHIFT) /* Pdelay_Req (in peer-to-peer
+ * transparent clock) or Announce (in
+ * ordinary or boundary clock) */
+# define ETH_RDES4_PMT_PDELREQMM (6 << ETH_RDES4_PMT_SHIFT) /* Pdelay_Resp (in peer-to-peer
+ * transparent clock) or Management (in
+ * ordinary or boundary clock) */
+# define ETH_RDES4_PMT_PDELREQFUS (7 << ETH_RDES4_PMT_SHIFT) /* Pdelay_Resp_Follow_Up (in
+ * peer-to-peer transparent clock) or
+ * Signaling (for ordinary or boundary
+ * clock) */
+#define ETH_RDES4_PFT (1 << 12) /* Bit 12: PTP frame type */
+#define ETH_RDES4_PV (1 << 13) /* Bit 13: PTP version */
+
+/* RDES5: Receive descriptor Word5 - Reserved */
+/* RDES6: Receive descriptor Word6 (32-bit time stamp) */
+/* RDES7: Receive descriptor Word7 (32-bit time stamp) */
+
+/****************************************************************************************************
+ * Public Types
+ ****************************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/* Ethernet TX DMA Descriptor */
+
+struct eth_txdesc_s
+{
+ /* Normal DMA descriptor words */
+
+ volatile uint32_t tdes0; /* Status */
+ volatile uint32_t tdes1; /* Control and buffer1/2 lengths */
+ volatile uint32_t tdes2; /* Buffer1 address pointer */
+ volatile uint32_t tdes3; /* Buffer2 or next descriptor address pointer */
+
+ /* Enhanced DMA descriptor words with time stamp */
+
+#ifdef CONFIG_STM32_ETH_ENHANCEDDESC
+ volatile uint32_t tdes4; /* Reserved */
+ volatile uint32_t tdes5; /* Reserved */
+ volatile uint32_t tdes6; /* Time Stamp Low value for transmit and receive */
+ volatile uint32_t tdes7; /* Time Stamp High value for transmit and receive */
+#endif
+};
+
+/* Ethernet RX DMA Descriptor */
+
+struct eth_rxdesc_s
+{
+ volatile uint32_t rdes0; /* Status */
+ volatile uint32_t rdes1; /* Control and buffer1/2 lengths */
+ volatile uint32_t rdes2; /* Buffer1 address pointer */
+ volatile uint32_t rdes3; /* Buffer2 or next descriptor address pointer */
+
+ /* Enhanced DMA descriptor words with time stamp and PTP support */
+
+#ifdef CONFIG_STM32_ETH_ENHANCEDDESC
+ volatile uint32_t rdes4; /* Extended status for PTP receive descriptor */
+ volatile uint32_t rdes5; /* Reserved */
+ volatile uint32_t rdes6; /* Time Stamp Low value for transmit and receive */
+ volatile uint32_t rdes7; /* Time Stamp High value for transmit and receive */
+#endif
+};
+
+/****************************************************************************************************
+ * Public Functions
+ ****************************************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* STM32_NETHERNET > 0 */
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_ETH_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_exti.h b/nuttx/arch/arm/src/stm32/chip/stm32_exti.h
new file mode 100644
index 000000000..82477db54
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_exti.h
@@ -0,0 +1,141 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_exti.h
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_CHIP_STM32_EXTI_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_EXTI_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# ifdef CONFIG_STM32_CONNECTIVITYLINE
+# define STM32_NEXTI 20
+# define STM32_EXTI_MASK 0x000fffff
+# else
+# define STM32_NEXTI 19
+# define STM32_EXTI_MASK 0x0007ffff
+# endif
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_NEXTI 23
+# define STM32_EXTI_MASK 0x007fffff
+#endif
+
+#define STM32_EXTI_BIT(n) (1 << (n))
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_EXTI_IMR_OFFSET 0x0000 /* Interrupt mask register */
+#define STM32_EXTI_EMR_OFFSET 0x0004 /* Event mask register */
+#define STM32_EXTI_RTSR_OFFSET 0x0008 /* Rising Trigger selection register */
+#define STM32_EXTI_FTSR_OFFSET 0x000c /* Falling Trigger selection register */
+#define STM32_EXTI_SWIER_OFFSET 0x0010 /* Software interrupt event register */
+#define STM32_EXTI_PR_OFFSET 0x0014 /* Pending register */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_EXTI_IMR (STM32_EXTI_BASE+STM32_EXTI_IMR_OFFSET)
+#define STM32_EXTI_EMR (STM32_EXTI_BASE+STM32_EXTI_EMR_OFFSET)
+#define STM32_EXTI_RTSR (STM32_EXTI_BASE+STM32_EXTI_RTSR_OFFSET)
+#define STM32_EXTI_FTSR (STM32_EXTI_BASE+STM32_EXTI_FTSR_OFFSET)
+#define STM32_EXTI_SWIER (STM32_EXTI_BASE+STM32_EXTI_SWIER_OFFSET)
+#define STM32_EXTI_PR (STM32_EXTI_BASE+STM32_EXTI_PR_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* EXTI lines > 15 are associated with internal devices: */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# define EXTI_PVD_LINE (1 << 16) /* EXTI line 16 is connected to the PVD output */
+# define EXTI_RTC_ALARM (1 << 17) /* EXTI line 17 is connected to the RTC Alarm event */
+# define EXTI_USB_WAKEUP (1 << 18) /* EXTI line 18 is connected to the USB Wakeup event */
+# ifdef CONFIG_STM32_CONNECTIVITYLINE
+# define EXTI_ETH_WAKEUP (1 << 19) /* EXTI line 19 is connected to the Ethernet Wakeup event */
+# endif
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define EXTI_PVD_LINE (1 << 16) /* EXTI line 16 is connected to the PVD output */
+# define EXTI_RTC_ALARM (1 << 17) /* EXTI line 17 is connected to the RTC Alarm event */
+# define EXTI_OTGFS_WAKEUP (1 << 18) /* EXTI line 18 is connected to the USB OTG FS Wakeup event */
+# define EXTI_ETH_WAKEUP (1 << 19) /* EXTI line 19 is connected to the Ethernet Wakeup event */
+# define EXTI_OTGHS_WAKEUP (1 << 20) /* EXTI line 20 is connected to the USB OTG HS Wakeup event */
+# define EXTI_RTC_TAMPER (1 << 21) /* EXTI line 21 is connected to the RTC Tamper and TimeStamp events */
+# define EXTI_RTC_TIMESTAMP (1 << 22) /* EXTI line 21 is connected to the RTC Tamper and TimeStamp events */
+# define EXTI_RTC_WAKEUP (1 << 23) /* EXTI line 22 is connected to the RTC Wakeup event */
+#endif
+
+/* Interrupt mask register */
+
+#define EXTI_IMR_BIT(n) STM32_EXTI_BIT(n) /* 1=Interrupt request from line x is not masked */
+#define EXTI_IMR_SHIFT (0) /* Bits 0-X: Interrupt Mask for all lines */
+#define EXTI_IMR_MASK STM32_EXTI_MASK
+
+/* Event mask register */
+
+#define EXTI_EMR_BIT(n) STM32_EXTI_BIT(n) /* 1=Event request from line x is not mask */
+#define EXTI_EMR_SHIFT (0) /* Bits Bits 0-X: Event Mask for all lines */
+#define EXTI_EMR_MASK STM32_EXTI_MASK
+
+/* Rising Trigger selection register */
+
+#define EXTI_RTSR_BIT(n) STM32_EXTI_BIT(n) /* 1=Rising trigger enabled (for Event and Interrupt) for input line */
+#define EXTI_RTSR_SHIFT (0) /* Bits 0-X: Rising trigger event configuration bit for all lines */
+#define EXTI_RTSR_MASK STM32_EXTI_MASK
+
+/* Falling Trigger selection register */
+
+#define EXTI_FTSR_BIT(n) STM32_EXTI_BIT(n) /* 1=Falling trigger enabled (for Event and Interrupt) for input line */
+#define EXTI_FTSR_SHIFT (0) /* Bits 0-X: Falling trigger event configuration bitfor all lines */
+#define EXTI_FTSR_MASK STM32_EXTI_MASK
+
+/* Software interrupt event register */
+
+#define EXTI_SWIER_BIT(n) STM32_EXTI_BIT(n) /* 1=Sets the corresponding pending bit in EXTI_PR */
+#define EXTI_SWIER_SHIFT (0) /* Bits 0-X: Software Interrupt for all lines */
+#define EXTI_SWIER_MASK STM32_EXTI_MASK
+
+/* Pending register */
+
+#define EXTI_IMR_BIT(n) STM32_EXTI_BIT(n) /* 1=Selected trigger request occurred */
+#define EXTI_IMR_SHIFT (0) /* Bits 0-X: Pending bit for all lines */
+#define EXTI_IMR_MASK STM32_EXTI_MASK
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_EXTI_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_flash.h b/nuttx/arch/arm/src/stm32/chip/stm32_flash.h
new file mode 100644
index 000000000..c2e440923
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_flash.h
@@ -0,0 +1,190 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_flash.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_CHIP_STM32_FLASH_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_FLASH_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#if defined(CONFIG_STM32_LOWDENSITY)
+# define STM32_FLASH_NPAGES 32
+# define STM32_FLASH_PAGESIZE 1024
+#elif defined(CONFIG_STM32_MEDIUMDENSITY)
+# define STM32_FLASH_NPAGES 128
+# define STM32_FLASH_PAGESIZE 1024
+#elif defined(CONFIG_STM32_CONNECTIVITYLINE)
+# define STM32_FLASH_NPAGES 128
+# define STM32_FLASH_PAGESIZE 2048
+#elif defined(CONFIG_STM32_HIGHDENSITY)
+# define STM32_FLASH_NPAGES 256
+# define STM32_FLASH_PAGESIZE 2048
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_FLASH_NPAGES 8
+# define STM32_FLASH_PAGESIZE (128*1024)
+#endif
+
+#define STM32_FLASH_SIZE (STM32_FLASH_NPAGES * STM32_FLASH_PAGESIZE)
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_FLASH_ACR_OFFSET 0x0000
+#define STM32_FLASH_KEYR_OFFSET 0x0004
+#define STM32_FLASH_OPTKEYR_OFFSET 0x0008
+#define STM32_FLASH_SR_OFFSET 0x000c
+#define STM32_FLASH_CR_OFFSET 0x0010
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# define STM32_FLASH_AR_OFFSET 0x0014
+# define STM32_FLASH_OBR_OFFSET 0x001c
+# define STM32_FLASH_WRPR_OFFSET 0x0020
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_FLASH_OPTCR_OFFSET 0x0014
+#endif
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_FLASH_ACR (STM32_FLASHIF_BASE+STM32_FLASH_ACR_OFFSET)
+#define STM32_FLASH_KEYR (STM32_FLASHIF_BASE+STM32_FLASH_KEYR_OFFSET)
+#define STM32_FLASH_OPTKEYR (STM32_FLASHIF_BASE+STM32_FLASH_OPTKEYR_OFFSET)
+#define STM32_FLASH_SR (STM32_FLASHIF_BASE+STM32_FLASH_SR_OFFSET)
+#define STM32_FLASH_CR (STM32_FLASHIF_BASE+STM32_FLASH_CR_OFFSET)
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# define STM32_FLASH_AR (STM32_FLASHIF_BASE+STM32_FLASH_AR_OFFSET)
+# define STM32_FLASH_OBR (STM32_FLASHIF_BASE+STM32_FLASH_OBR_OFFSET)
+# define STM32_FLASH_WRPR (STM32_FLASHIF_BASE+STM32_FLASH_WRPR_OFFSET)
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_FLASH_OPTCR (STM32_FLASHIF_BASE+STM32_FLASH_OPTCR_OFFSET)
+#endif
+
+/* Register Bitfield Definitions ****************************************************/
+/* Flash Access Control Register (ACR) */
+
+#define FLASH_ACR_LATENCY_SHIFT (0)
+#define FLASH_ACR_LATENCY_MASK (7 << FLASH_ACR_LATENCY_SHIFT)
+# define FLASH_ACR_LATENCY(n) ((n) << FLASH_ACR_LATENCY_SHIFT) /* n wait states */
+# define FLASH_ACR_LATENCY_0 (0 << FLASH_ACR_LATENCY_SHIFT) /* 000: Zero wait states */
+# define FLASH_ACR_LATENCY_1 (1 << FLASH_ACR_LATENCY_SHIFT) /* 001: One wait state */
+# define FLASH_ACR_LATENCY_2 (2 << FLASH_ACR_LATENCY_SHIFT) /* 010: Two wait states */
+# define FLASH_ACR_LATENCY_3 (3 << FLASH_ACR_LATENCY_SHIFT) /* 011: Three wait states */
+# define FLASH_ACR_LATENCY_4 (4 << FLASH_ACR_LATENCY_SHIFT) /* 100: Four wait states */
+# define FLASH_ACR_LATENCY_5 (5 << FLASH_ACR_LATENCY_SHIFT) /* 101: Five wait states */
+# define FLASH_ACR_LATENCY_6 (6 << FLASH_ACR_LATENCY_SHIFT) /* 110: Six wait states */
+# define FLASH_ACR_LATENCY_7 (7 << FLASH_ACR_LATENCY_SHIFT) /* 111: Seven wait states */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# define FLASH_ACR_HLFCYA (1 << 3) /* FLASH half cycle access */
+# define FLASH_ACR_PRTFBE (1 << 4) /* FLASH prefetch enable */
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define FLASH_ACR_ICEN (1 << 9) /* Bit 9: Instruction cache enable */
+# define FLASH_ACR_DCEN (1 << 10) /* Bit 10: Data cache enable */
+# define FLASH_ACR_ICRST (1 << 11) /* Bit 11: Instruction cache reset */
+# define FLASH_ACR_DCRST (1 << 12) /* Bit 12: Data cache reset */
+#endif
+
+/* Flash Status Register (SR) */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# define FLASH_SR_BSY (1 << 0) /* Busy */
+# define FLASH_SR_PGERR (1 << 2) /* Programming Error */
+# define FLASH_SR_WRPRT_ERR (1 << 4) /* Write Protection Error */
+# define FLASH_SR_EOP (1 << 5) /* End of Operation */
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define FLASH_SR_EOP (1 << 0) /* Bit 0: End of operation */
+# define FLASH_SR_OPERR (1 << 1) /* Bit 1: Operation error */
+# define FLASH_SR_WRPERR (1 << 4) /* Bit 4: Write protection error */
+# define FLASH_SR_PGAERR (1 << 5) /* Bit 5: Programming alignment error */
+# define FLASH_SR_PGPERR (1 << 6) /* Bit 6: Programming parallelism error */
+# define FLASH_SR_PGSERR (1 << 7) /* Bit 7: Programming sequence error */
+# define FLASH_SR_BSY (1 << 16) /* Bit 16: Busy */
+#endif
+
+/* Flash Control Register (CR) */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# define FLASH_CR_PG (1 << 0) /* Program Page */
+# define FLASH_CR_PER (1 << 1) /* Page Erase */
+# define FLASH_CR_MER (1 << 2) /* Mass Erase */
+# define FLASH_CR_OPTPG (1 << 4) /* Option Byte Programming */
+# define FLASH_CR_OPTER (1 << 5) /* Option Byte Erase */
+# define FLASH_CR_STRT (1 << 6) /* Start Erase */
+# define FLASH_CR_LOCK (1 << 7) /* Page Locked or Lock Page */
+# define FLASH_CR_OPTWRE (1 << 9) /* Option Bytes Write Enable */
+# define FLASH_CR_ERRIE (1 << 10) /* Error Interrupt Enable */
+# define FLASH_CR_EOPIE (1 << 12) /* End of Program Interrupt Enable */
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define FLASH_CR_PG (1 << 0) /* Bit 0: Programming */
+# define FLASH_CR_SER (1 << 1) /* Bit 1: Sector Erase */
+# define FLASH_CR_MER (1 << 2) /* Bit 2: Mass Erase */
+# define FLASH_CR_SNB_SHIFT (3) /* Bits 3-6: Sector number */
+# define FLASH_CR_SNB_MASK (15 << FLASH_CR_SNB_SHIFT)
+# define FLASH_CR_SNB(n) ((n) << FLASH_CR_SNB_SHIFT) /* Sector n, n=0..11 */
+# define FLASH_CR_PSIZE_SHIFT (8) /* Bits 8-9: Program size */
+# define FLASH_CR_PSIZE_MASK (3 << FLASH_CR_PSIZE_SHIFT)
+# define FLASH_CR_PSIZE_X8 (0 << FLASH_CR_PSIZE_SHIFT) /* 00 program x8 */
+# define FLASH_CR_PSIZE_X16 (1 << FLASH_CR_PSIZE_SHIFT) /* 01 program x16 */
+# define FLASH_CR_PSIZE_X32 (2 << FLASH_CR_PSIZE_SHIFT) /* 10 program x32 */
+# define FLASH_CR_PSIZE_X64 (3 << FLASH_CR_PSIZE_SHIFT) /* 11 program x64 */
+# define FLASH_CR_EOPIE (1 << 24) /* Bit 24: End of operation interrupt enable */
+# define FLASH_CR_ERRIE (1 << 25) /* Bit 25: Error interrupt enable */
+# define FLASH_CR_LOCK (1 << 31) /* Bit 31: Lock */
+#endif
+
+/* Flash Option Control Register (OPTCR) */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define FLASH_OPTCR_OPTLOCK (1 << 0) /* Bit 0: Option lock */
+# define FLASH_OPTCR_OPTSTRT (1 << 1) /* Bit 1: Option start */
+# define FLASH_OPTCR_BORLEV_SHIFT (2) /* Bits 2-3: BOR reset Level */
+# define FLASH_OPTCR_BORLEV_MASK (3 << FLASH_OPTCR_BORLEV_SHIFT)
+# define FLASH_OPTCR_VBOR3 (0 << FLASH_OPTCR_BORLEV_SHIFT) /* 00: BOR Level 3 */
+# define FLASH_OPTCR_VBOR2 (1 << FLASH_OPTCR_BORLEV_SHIFT) /* 01: BOR Level 2 */
+# define FLASH_OPTCR_VBOR1 (2 << FLASH_OPTCR_BORLEV_SHIFT) /* 10: BOR Level 1 */
+# define FLASH_OPTCR_VBOR0 (3 << FLASH_OPTCR_BORLEV_SHIFT) /* 11: BOR off */
+# define FLASH_OPTCR_USER_SHIFT (5) /* Bits 5-7: User option bytes */
+# define FLASH_OPTCR_USER_MASK (7 << FLASH_OPTCR_USER_SHIFT)
+# define FLASH_OPTCR_NRST_STDBY (1 << 7) /* Bit 7: nRST_STDBY */
+# define FLASH_OPTCR_NRST_STOP (1 << 6) /* Bit 6: nRST_STOP */
+# define FLASH_OPTCR_WDG_SW (1 << 5) /* Bit 5: WDG_SW */
+# define FLASH_OPTCR_RDP_SHIFT (8) /* Bits 8-15: Read protect */
+# define FLASH_OPTCR_RDP_MASK (0xff << FLASH_OPTCR_RDP_SHIFT)
+# define FLASH_OPTCR_NWRP_SHIFT (16) /* Bits 16-27: Not write protect */
+# define FLASH_OPTCR_NWRP_MASK (0xfff << FLASH_OPTCR_NWRP_SHIFT)
+#endif
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_FLASH_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h b/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h
new file mode 100644
index 000000000..f481245e0
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h
@@ -0,0 +1,192 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_i2c.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_CHIP_STM32_I2C_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_I2C_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_I2C_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */
+#define STM32_I2C_CR2_OFFSET 0x0004 /* Control register 2 (16-bit) */
+#define STM32_I2C_OAR1_OFFSET 0x0008 /* Own address register 1 (16-bit) */
+#define STM32_I2C_OAR2_OFFSET 0x000c /* Own address register 2 (16-bit) */
+#define STM32_I2C_DR_OFFSET 0x0010 /* Data register (16-bit) */
+#define STM32_I2C_SR1_OFFSET 0x0014 /* Status register 1 (16-bit) */
+#define STM32_I2C_SR2_OFFSET 0x0018 /* Status register 2 (16-bit) */
+#define STM32_I2C_CCR_OFFSET 0x001c /* Clock control register (16-bit) */
+#define STM32_I2C_TRISE_OFFSET 0x0020 /* TRISE Register (16-bit) */
+
+/* Register Addresses ***************************************************************/
+
+#if STM32_NI2C > 0
+# define STM32_I2C1_CR1 (STM32_I2C1_BASE+STM32_I2C_CR1_OFFSET)
+# define STM32_I2C1_CR2 (STM32_I2C1_BASE+STM32_I2C_CR2_OFFSET)
+# define STM32_I2C1_OAR1 (STM32_I2C1_BASE+STM32_I2C_OAR1_OFFSET)
+# define STM32_I2C1_OAR2 (STM32_I2C1_BASE+STM32_I2C_OAR2_OFFSET)
+# define STM32_I2C1_DR (STM32_I2C1_BASE+STM32_I2C_DR_OFFSET)
+# define STM32_I2C1_SR1 (STM32_I2C1_BASE+STM32_I2C_SR1_OFFSET)
+# define STM32_I2C1_SR2 (STM32_I2C1_BASE+STM32_I2C_SR2_OFFSET)
+# define STM32_I2C1_CCR (STM32_I2C1_BASE+STM32_I2C_CCR_OFFSET)
+# define STM32_I2C1_TRISE (STM32_I2C1_BASE+STM32_I2C_TRISE_OFFSET)
+#endif
+
+#if STM32_NI2C > 1
+# define STM32_I2C2_CR1 (STM32_I2C2_BASE+STM32_I2C_CR1_OFFSET)
+# define STM32_I2C2_CR2 (STM32_I2C2_BASE+STM32_I2C_CR2_OFFSET)
+# define STM32_I2C2_OAR1 (STM32_I2C2_BASE+STM32_I2C_OAR1_OFFSET)
+# define STM32_I2C2_OAR2 (STM32_I2C2_BASE+STM32_I2C_OAR2_OFFSET)
+# define STM32_I2C2_DR (STM32_I2C2_BASE+STM32_I2C_DR_OFFSET)
+# define STM32_I2C2_SR1 (STM32_I2C2_BASE+STM32_I2C_SR1_OFFSET)
+# define STM32_I2C2_SR2 (STM32_I2C2_BASE+STM32_I2C_SR2_OFFSET)
+# define STM32_I2C2_CCR (STM32_I2C2_BASE+STM32_I2C_CCR_OFFSET)
+# define STM32_I2C2_TRISE (STM32_I2C2_BASE+STM32_I2C_TRISE_OFFSET)
+#endif
+
+#if STM32_NI2C > 2
+# define STM32_I2C3_CR1 (STM32_I2C3_BASE+STM32_I2C_CR1_OFFSET)
+# define STM32_I2C3_CR2 (STM32_I2C3_BASE+STM32_I2C_CR2_OFFSET)
+# define STM32_I2C3_OAR1 (STM32_I2C3_BASE+STM32_I2C_OAR1_OFFSET)
+# define STM32_I2C3_OAR2 (STM32_I2C3_BASE+STM32_I2C_OAR2_OFFSET)
+# define STM32_I2C3_DR (STM32_I2C3_BASE+STM32_I2C_DR_OFFSET)
+# define STM32_I2C3_SR1 (STM32_I2C3_BASE+STM32_I2C_SR1_OFFSET)
+# define STM32_I2C3_SR2 (STM32_I2C3_BASE+STM32_I2C_SR2_OFFSET)
+# define STM32_I2C3_CCR (STM32_I2C3_BASE+STM32_I2C_CCR_OFFSET)
+# define STM32_I2C3_TRISE (STM32_I2C3_BASE+STM32_I2C_TRISE_OFFSET)
+#endif
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* Control register 1 */
+
+#define I2C_CR1_PE (1 << 0) /* Bit 0: Peripheral Enable */
+#define I2C_CR1_SMBUS (1 << 1) /* Bit 1: SMBus Mode */
+#define I2C_CR1_SMBTYPE (1 << 3) /* Bit 3: SMBus Type */
+#define I2C_CR1_ENARP (1 << 4) /* Bit 4: ARP Enable */
+#define I2C_CR1_ENPEC (1 << 5) /* Bit 5: PEC Enable */
+#define I2C_CR1_ENGC (1 << 6) /* Bit 6: General Call Enable */
+#define I2C_CR1_NOSTRETCH (1 << 7) /* Bit 7: Clock Stretching Disable (Slave mode) */
+#define I2C_CR1_START (1 << 8) /* Bit 8: Start Generation */
+#define I2C_CR1_STOP (1 << 9) /* Bit 9: Stop Generation */
+#define I2C_CR1_ACK (1 << 10) /* Bit 10: Acknowledge Enable */
+#define I2C_CR1_POS (1 << 11) /* Bit 11: Acknowledge/PEC Position (for data reception) */
+#define I2C_CR1_PEC (1 << 12) /* Bit 12: Packet Error Checking */
+#define I2C_CR1_ALERT (1 << 13) /* Bit 13: SMBus Alert */
+#define I2C_CR1_SWRST (1 << 15) /* Bit 15: Software Reset */
+
+/* Control register 2 */
+
+#define I2C_CR2_FREQ_SHIFT (0) /* Bits 5-0: Peripheral Clock Frequency */
+#define I2C_CR2_FREQ_MASK (0x3f << I2C_CR2_FREQ_SHIFT)
+#define I2C_CR2_ITERREN (1 << 8) /* Bit 8: Error Interrupt Enable */
+#define I2C_CR2_ITEVFEN (1 << 9) /* Bit 9: Event Interrupt Enable */
+#define I2C_CR2_ITBUFEN (1 << 10) /* Bit 10: Buffer Interrupt Enable */
+#define I2C_CR2_DMAEN (1 << 11) /* Bit 11: DMA Requests Enable */
+#define I2C_CR2_LAST (1 << 12) /* Bit 12: DMA Last Transfer */
+
+#define I2C_CR2_ALLINTS (I2C_CR2_ITERREN|I2C_CR2_ITEVFEN|I2C_CR2_ITBUFEN)
+
+/* Own address register 1 */
+
+#define I2C_OAR1_ADD0 (1 << 0) /* Bit 0: Interface Address */
+#define I2C_OAR1_ADD8_SHIFT (1) /* Bits 7-1: Interface Address */
+#define I2C_OAR1_ADD8_MASK (0x007f << I2C_OAR1_ADD8_SHIFT)
+#define I2C_OAR1_ADD10_SHIFT (1) /* Bits 9-1: Interface Address (10-bit addressing mode)*/
+#define I2C_OAR1_ADD10_MASK (0x01ff << I2C_OAR1_ADD10_SHIFT)
+#define I2C_OAR1_ONE (1 << 14) /* Bit 14: Must be configured and kept at 1 */
+#define I2C_OAR1_ADDMODE (1 << 15) /* Bit 15: Addressing Mode (Slave mode) */
+
+/* Own address register 2 */
+
+#define I2C_OAR2_ENDUAL (1 << 0) /* Bit 0: Dual addressing mode enable */
+#define I2C_OAR2_ADD2_SHIFT (1) /* Bits 7-1: Interface address */
+#define I2C_OAR2_ADD2_MASK (0x7f << I2C_OAR2_ADD2_SHIFT)
+
+/* Data register */
+
+#define I2C_DR_SHIFT (0) /* Bits 7-0: 8-bit Data Register */
+#define I2C_DR_MASK (0x00ff << I2C_DR_SHIFT)
+
+/* Status register 1 */
+
+#define I2C_SR1_SB (1 << 0) /* Bit 0: Start Bit (Master mode) */
+#define I2C_SR1_ADDR (1 << 1) /* Bit 1: Address sent (master mode)/matched (slave mode) */
+#define I2C_SR1_BTF (1 << 2) /* Bit 2: Byte Transfer Finished */
+#define I2C_SR1_ADD10 (1 << 3) /* Bit 3: 10-bit header sent (Master mode) */
+#define I2C_SR1_STOPF (1 << 4) /* Bit 4: Stop detection (Slave mode) */
+ /* Bit 5: Reserved */
+#define I2C_SR1_RXNE (1 << 6) /* Bit 6: Data Register not Empty (receivers) */
+#define I2C_SR1_TXE (1 << 7) /* Bit 7: Data Register Empty (transmitters) */
+#define I2C_SR1_BERR (1 << 8) /* Bit 8: Bus Error */
+#define I2C_SR1_ARLO (1 << 9) /* Bit 9: Arbitration Lost (master mode) */
+#define I2C_SR1_AF (1 << 10) /* Bit 10: Acknowledge Failure */
+#define I2C_SR1_OVR (1 << 11) /* Bit 11: Overrun/Underrun */
+#define I2C_SR1_PECERR (1 << 12) /* Bit 12: PEC Error in reception */
+ /* Bit 13: Reserved */
+#define I2C_SR1_TIMEOUT (1 << 14) /* Bit 14: Timeout or Tlow Error */
+#define I2C_SR1_SMBALERT (1 << 15) /* Bit 15: SMBus Alert */
+
+#define I2C_SR1_ERRORMASK (I2C_SR1_BERR|I2C_SR1_ARLO|I2C_SR1_AF|I2C_SR1_OVR|\
+ I2C_SR1_PECERR|I2C_SR1_TIMEOUT|I2C_SR1_SMBALERT)
+
+/* Status register 2 */
+
+#define I2C_SR2_MSL (1 << 0) /* Bit 0: Master/Slave */
+#define I2C_SR2_BUSY (1 << 1) /* Bit 1: Bus Busy */
+#define I2C_SR2_TRA (1 << 2) /* Bit 2: Transmitter/Receiver */
+#define I2C_SR2_GENCALL (1 << 4) /* Bit 4: General Call Address (Slave mode) */
+#define I2C_SR2_SMBDEFAULT (1 << 5) /* Bit 5: SMBus Device Default Address (Slave mode) */
+#define I2C_SR2_SMBHOST (1 << 6) /* Bit 6: SMBus Host Header (Slave mode) */
+#define I2C_SR2_DUALF (1 << 7) /* Bit 7: Dual Flag (Slave mode) */
+#define I2C_SR2_PEC_SHIFT (1) /* Bits 15-8: Packet Error Checking Register */
+#define I2C_SR2_PEC_MASK (0xff << I2C_SR2_PEC_SHIFT)
+
+/* Clock control register */
+
+#define I2C_CCR_CCR_SHIFT (0) /* Bits 11-0: Clock Control Register in Fast/Standard mode (Master mode) */
+#define I2C_CCR_CCR_MASK (0x0fff << I2C_CCR_CCR_SHIFT)
+#define I2C_CCR_DUTY (1 << 14) /* Bit 14: Fast Mode Duty Cycle */
+#define I2C_CCR_FS (1 << 15) /* Bit 15: Fast Mode Selection */
+
+/* TRISE Register */
+
+#define I2C_TRISE_SHIFT (0) /* Bits 5-0: Maximum Rise Time in Fast/Standard mode (Master mode) */
+#define I2C_TRISE_MASK (0x3f << I2C_TRISE_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_I2C_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_memorymap.h b/nuttx/arch/arm/src/stm32/chip/stm32_memorymap.h
new file mode 100644
index 000000000..a53c7441c
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_memorymap.h
@@ -0,0 +1,57 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_memorymap.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_CHIP_STM32_MEMORYMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_MEMORYMAP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "chip/stm32f10xxx_memorymap.h"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/stm32f20xxx_memorymap.h"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32f40xxx_memorymap.h"
+#else
+# error "Unsupported STM32 memory map"
+#endif
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_MEMORYMAP_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_otgfs.h b/nuttx/arch/arm/src/stm32/chip/stm32_otgfs.h
new file mode 100644
index 000000000..d3bf7eb54
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_otgfs.h
@@ -0,0 +1,1002 @@
+/****************************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_otgfs.h
+ *
+ * Copyright (C) 2012 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_STM32_CHIP_STM32_OTGFS_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_OTGFS_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+/****************************************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************************************/
+
+/* Register Offsets *********************************************************************************/
+/* Core global control and status registers */
+
+#define STM32_OTGFS_GOTGCTL_OFFSET 0x0000 /* Control and status register */
+#define STM32_OTGFS_GOTGINT_OFFSET 0x0004 /* Interrupt register */
+#define STM32_OTGFS_GAHBCFG_OFFSET 0x0008 /* AHB configuration register */
+#define STM32_OTGFS_GUSBCFG_OFFSET 0x000c /* USB configuration register */
+#define STM32_OTGFS_GRSTCTL_OFFSET 0x0010 /* Reset register */
+#define STM32_OTGFS_GINTSTS_OFFSET 0x0014 /* Core interrupt register */
+#define STM32_OTGFS_GINTMSK_OFFSET 0x0018 /* Interrupt mask register */
+#define STM32_OTGFS_GRXSTSR_OFFSET 0x001c /* Receive status debug read/OTG status read register */
+#define STM32_OTGFS_GRXSTSP_OFFSET 0x0020 /* Receive status debug read/OTG status pop register */
+#define STM32_OTGFS_GRXFSIZ_OFFSET 0x0024 /* Receive FIFO size register */
+#define STM32_OTGFS_HNPTXFSIZ_OFFSET 0x0028 /* Host non-periodic transmit FIFO size register */
+#define STM32_OTGFS_DIEPTXF0_OFFSET 0x0028 /* Endpoint 0 Transmit FIFO size */
+#define STM32_OTGFS_HNPTXSTS_OFFSET 0x002c /* Non-periodic transmit FIFO/queue status register */
+#define STM32_OTGFS_GCCFG_OFFSET 0x0038 /* general core configuration register */
+#define STM32_OTGFS_CID_OFFSET 0x003c /* Core ID register */
+#define STM32_OTGFS_HPTXFSIZ_OFFSET 0x0100 /* Host periodic transmit FIFO size register */
+
+#define STM32_OTGFS_DIEPTXF_OFFSET(n) (104+(((n)-1) << 2))
+#define STM32_OTGFS_DIEPTXF1_OFFSET 0x0104 /* Device IN endpoint transmit FIFO1 size register */
+#define STM32_OTGFS_DIEPTXF2_OFFSET 0x0108 /* Device IN endpoint transmit FIFO2 size register */
+#define STM32_OTGFS_DIEPTXF3_OFFSET 0x010c /* Device IN endpoint transmit FIFO3 size register */
+
+/* Host-mode control and status registers */
+
+#define STM32_OTGFS_HCFG_OFFSET 0x0400 /* Host configuration register */
+#define STM32_OTGFS_HFIR_OFFSET 0x0404 /* Host frame interval register */
+#define STM32_OTGFS_HFNUM_OFFSET 0x0408 /* Host frame number/frame time remaining register */
+#define STM32_OTGFS_HPTXSTS_OFFSET 0x0410 /* Host periodic transmit FIFO/queue status register */
+#define STM32_OTGFS_HAINT_OFFSET 0x0414 /* Host all channels interrupt register */
+#define STM32_OTGFS_HAINTMSK_OFFSET 0x0418 /* Host all channels interrupt mask register */
+#define STM32_OTGFS_HPRT_OFFSET 0x0440 /* Host port control and status register */
+
+#define STM32_OTGFS_CHAN_OFFSET(n) (0x500 + ((n) << 5)
+#define STM32_OTGFS_HCCHAR_CHOFFSET 0x0000 /* Host channel characteristics register */
+#define STM32_OTGFS_HCINT_CHOFFSET 0x0008 /* Host channel interrupt register */
+#define STM32_OTGFS_HCINTMSK_CHOFFSET 0x000c /* Host channel interrupt mask register */
+#define STM32_OTGFS_HCTSIZ_CHOFFSET 0x0010 /* Host channel interrupt register */
+
+#define STM32_OTGFS_HCCHAR_OFFSET(n) (0x500 + ((n) << 5))
+#define STM32_OTGFS_HCCHAR0_OFFSET 0x0500 /* Host channel-0 characteristics register */
+#define STM32_OTGFS_HCCHAR1_OFFSET 0x0520 /* Host channel-1 characteristics register */
+#define STM32_OTGFS_HCCHAR2_OFFSET 0x0540 /* Host channel-2 characteristics register */
+#define STM32_OTGFS_HCCHAR3_OFFSET 0x0560 /* Host channel-3 characteristics register */
+#define STM32_OTGFS_HCCHAR4_OFFSET 0x0580 /* Host channel-4 characteristics register */
+#define STM32_OTGFS_HCCHAR5_OFFSET 0x05a0 /* Host channel-5 characteristics register */
+#define STM32_OTGFS_HCCHAR6_OFFSET 0x05c0 /* Host channel-6 characteristics register */
+#define STM32_OTGFS_HCCHAR7_OFFSET 0x05e0 /* Host channel-7 characteristics register */
+
+#define STM32_OTGFS_HCINT_OFFSET(n) (0x508 + ((n) << 5))
+#define STM32_OTGFS_HCINT0_OFFSET 0x0508 /* Host channel-0 interrupt register */
+#define STM32_OTGFS_HCINT1_OFFSET 0x0528 /* Host channel-1 interrupt register */
+#define STM32_OTGFS_HCINT2_OFFSET 0x0548 /* Host channel-2 interrupt register */
+#define STM32_OTGFS_HCINT3_OFFSET 0x0568 /* Host channel-3 interrupt register */
+#define STM32_OTGFS_HCINT4_OFFSET 0x0588 /* Host channel-4 interrupt register */
+#define STM32_OTGFS_HCINT5_OFFSET 0x05a8 /* Host channel-5 interrupt register */
+#define STM32_OTGFS_HCINT6_OFFSET 0x05c8 /* Host channel-6 interrupt register */
+#define STM32_OTGFS_HCINT7_OFFSET 0x05e8 /* Host channel-7 interrupt register */
+
+#define STM32_OTGFS_HCINTMSK_OFFSET(n) (0x50c + ((n) << 5))
+#define STM32_OTGFS_HCINTMSK0_OFFSET 0x050c /* Host channel-0 interrupt mask register */
+#define STM32_OTGFS_HCINTMSK1_OFFSET 0x052c /* Host channel-1 interrupt mask register */
+#define STM32_OTGFS_HCINTMSK2_OFFSET 0x054c /* Host channel-2 interrupt mask register */
+#define STM32_OTGFS_HCINTMSK3_OFFSET 0x056c /* Host channel-3 interrupt mask register */
+#define STM32_OTGFS_HCINTMSK4_OFFSET 0x058c /* Host channel-4 interrupt mask register */
+#define STM32_OTGFS_HCINTMSK5_OFFSET 0x05ac /* Host channel-5 interrupt mask register */
+#define STM32_OTGFS_HCINTMSK6_OFFSET 0x05cc /* Host channel-6 interrupt mask register */
+#define STM32_OTGFS_HCINTMSK7_OFFSET 0x05ec /* Host channel-7 interrupt mask register */
+
+#define STM32_OTGFS_HCTSIZ_OFFSET(n) (0x510 + ((n) << 5))
+#define STM32_OTGFS_HCTSIZ0_OFFSET 0x0510 /* Host channel-0 interrupt register */
+#define STM32_OTGFS_HCTSIZ1_OFFSET 0x0530 /* Host channel-1 interrupt register */
+#define STM32_OTGFS_HCTSIZ2_OFFSET 0x0550 /* Host channel-2 interrupt register */
+#define STM32_OTGFS_HCTSIZ3_OFFSET 0x0570 /* Host channel-3 interrupt register */
+#define STM32_OTGFS_HCTSIZ4_OFFSET 0x0590 /* Host channel-4 interrupt register */
+#define STM32_OTGFS_HCTSIZ5_OFFSET 0x05b0 /* Host channel-5 interrupt register */
+#define STM32_OTGFS_HCTSIZ6_OFFSET 0x05d9 /* Host channel-6 interrupt register */
+#define STM32_OTGFS_HCTSIZ7_OFFSET 0x05f9 /* Host channel-7 interrupt register */
+
+/* Device-mode control and status registers */
+
+#define STM32_OTGFS_DCFG_OFFSET 0x0800 /* Device configuration register */
+#define STM32_OTGFS_DCTL_OFFSET 0x0804 /* Device control register */
+#define STM32_OTGFS_DSTS_OFFSET 0x0808 /* Device status register */
+#define STM32_OTGFS_DIEPMSK_OFFSET 0x0810 /* Device IN endpoint common interrupt mask register */
+#define STM32_OTGFS_DOEPMSK_OFFSET 0x0814 /* Device OUT endpoint common interrupt mask register */
+#define STM32_OTGFS_DAINT_OFFSET 0x0818 /* Device all endpoints interrupt register */
+#define STM32_OTGFS_DAINTMSK_OFFSET 0x081c /* All endpoints interrupt mask register */
+#define STM32_OTGFS_DVBUSDIS_OFFSET 0x0828 /* Device VBUS discharge time register */
+#define STM32_OTGFS_DVBUSPULSE_OFFSET 0x082c /* Device VBUS pulsing time register */
+#define STM32_OTGFS_DIEPEMPMSK_OFFSET 0x0834 /* Device IN endpoint FIFO empty interrupt mask register */
+
+#define STM32_OTGFS_DIEP_OFFSET(n) (0x0900 + ((n) << 5))
+#define STM32_OTGFS_DIEPCTL_EPOFFSET 0x0000 /* Device endpoint control register */
+#define STM32_OTGFS_DIEPINT_EPOFFSET 0x0008 /* Device endpoint interrupt register */
+#define STM32_OTGFS_DIEPTSIZ_EPOFFSET 0x0010 /* Device IN endpoint transfer size register */
+#define STM32_OTGFS_DTXFSTS_EPOFFSET 0x0018 /* Device IN endpoint transmit FIFO status register */
+
+#define STM32_OTGFS_DIEPCTL_OFFSET(n) (0x0900 + ((n) << 5))
+#define STM32_OTGFS_DIEPCTL0_OFFSET 0x0900 /* Device control IN endpoint 0 control register */
+#define STM32_OTGFS_DIEPCTL1_OFFSET 0x0920 /* Device control IN endpoint 2 control register */
+#define STM32_OTGFS_DIEPCTL2_OFFSET 0x0940 /* Device control IN endpoint 3 control register */
+#define STM32_OTGFS_DIEPCTL3_OFFSET 0x0960 /* Device control IN endpoint 4 control register */
+
+#define STM32_OTGFS_DIEPINT_OFFSET(n) (0x0908 + ((n) << 5))
+#define STM32_OTGFS_DIEPINT0_OFFSET 0x0908 /* Device endpoint-0 interrupt register */
+#define STM32_OTGFS_DIEPINT1_OFFSET 0x0928 /* Device endpoint-1 interrupt register */
+#define STM32_OTGFS_DIEPINT2_OFFSET 0x0948 /* Device endpoint-2 interrupt register */
+#define STM32_OTGFS_DIEPINT3_OFFSET 0x0968 /* Device endpoint-3 interrupt register */
+
+#define STM32_OTGFS_DIEPTSIZ_OFFSET(n) (0x910 + ((n) << 5))
+#define STM32_OTGFS_DIEPTSIZ0_OFFSET 0x0910 /* Device IN endpoint 0 transfer size register */
+#define STM32_OTGFS_DIEPTSIZ1_OFFSET 0x0930 /* Device IN endpoint 1 transfer size register */
+#define STM32_OTGFS_DIEPTSIZ2_OFFSET 0x0950 /* Device IN endpoint 2 transfer size register */
+#define STM32_OTGFS_DIEPTSIZ3_OFFSET 0x0970 /* Device IN endpoint 3 transfer size register */
+
+#define STM32_OTGFS_DTXFSTS_OFFSET(n) (0x0918 + ((n) << 5))
+#define STM32_OTGFS_DTXFSTS0_OFFSET 0x0918 /* Device OUT endpoint-0 TxFIFO status register */
+#define STM32_OTGFS_DTXFSTS1_OFFSET 0x0938 /* Device OUT endpoint-1 TxFIFO status register */
+#define STM32_OTGFS_DTXFSTS2_OFFSET 0x0958 /* Device OUT endpoint-2 TxFIFO status register */
+#define STM32_OTGFS_DTXFSTS3_OFFSET 0x0978 /* Device OUT endpoint-3 TxFIFO status register */
+
+#define STM32_OTGFS_DOEP_OFFSET(n) (0x0b00 + ((n) << 5))
+#define STM32_OTGFS_DOEPCTL_EPOFFSET 0x0000 /* Device control OUT endpoint 0 control register */
+#define STM32_OTGFS_DOEPINT_EPOFFSET 0x0008 /* Device endpoint-x interrupt register */
+
+#define STM32_OTGFS_DOEPCTL_OFFSET(n) (0x0b00 + ((n) << 5))
+#define STM32_OTGFS_DOEPCTL0_OFFSET 0x00b00 /* Device OUT endpoint 0 control register */
+#define STM32_OTGFS_DOEPCTL1_OFFSET 0x00b20 /* Device OUT endpoint 1 control register */
+#define STM32_OTGFS_DOEPCTL2_OFFSET 0x00b40 /* Device OUT endpoint 2 control register */
+#define STM32_OTGFS_DOEPCTL3_OFFSET 0x00b60 /* Device OUT endpoint 3 control register */
+
+#define STM32_OTGFS_DOEPINT_OFFSET(n) (0x0b08 + ((n) << 5))
+#define STM32_OTGFS_DOEPINT0_OFFSET 0x00b08 /* Device endpoint-0 interrupt register */
+#define STM32_OTGFS_DOEPINT1_OFFSET 0x00b28 /* Device endpoint-1 interrupt register */
+#define STM32_OTGFS_DOEPINT2_OFFSET 0x00b48 /* Device endpoint-2 interrupt register */
+#define STM32_OTGFS_DOEPINT3_OFFSET 0x00b68 /* Device endpoint-3 interrupt register */
+
+#define STM32_OTGFS_DOEPTSIZ_OFFSET(n) (0x0b10 + ((n) << 5))
+#define STM32_OTGFS_DOEPTSIZ0_OFFSET 0x00b10 /* Device OUT endpoint-0 transfer size register */
+#define STM32_OTGFS_DOEPTSIZ1_OFFSET 0x00b30 /* Device OUT endpoint-1 transfer size register */
+#define STM32_OTGFS_DOEPTSIZ2_OFFSET 0x00b50 /* Device OUT endpoint-2 transfer size register */
+#define STM32_OTGFS_DOEPTSIZ3_OFFSET 0x00b70 /* Device OUT endpoint-3 transfer size register */
+
+/* Data FIFO (DFIFO) access registers */
+
+#define STM32_OTGFS_DFIFO_DEP_OFFSET(n) (0x1000 + ((n) << 12))
+#define STM32_OTGFS_DFIFO_HCH_OFFSET(n) (0x1000 + ((n) << 12))
+
+#define STM32_OTGFS_DFIFO_DEP0_OFFSET 0x1000 /* 0x1000-0x1ffc Device IN/OUT Endpoint 0 DFIFO Write/Read Access */
+#define STM32_OTGFS_DFIFO_HCH0_OFFSET 0x1000 /* 0x1000-0x1ffc Host OUT/IN Channel 0 DFIFO Read/Write Access */
+
+#define STM32_OTGFS_DFIFO_DEP1_OFFSET 0x2000 /* 0x2000-0x2ffc Device IN/OUT Endpoint 1 DFIFO Write/Read Access */
+#define STM32_OTGFS_DFIFO_HCH1_OFFSET 0x2000 /* 0x2000-0x2ffc Host OUT/IN Channel 1 DFIFO Read/Write Access */
+
+#define STM32_OTGFS_DFIFO_DEP2_OFFSET 0x3000 /* 0x3000-0x3ffc Device IN/OUT Endpoint 1 DFIFO Write/Read Access */
+#define STM32_OTGFS_DFIFO_HCH2_OFFSET 0x3000 /* 0x3000-0x3ffc Host OUT/IN Channel 1 DFIFO Read/Write Access */
+
+#define STM32_OTGFS_DFIFO_DEP3_OFFSET 0x4000 /* 0x4000-0x4ffc Device IN/OUT Endpoint 1 DFIFO Write/Read Access */
+#define STM32_OTGFS_DFIFO_HCH3_OFFSET 0x4000 /* 0x4000-0x4ffc Host OUT/IN Channel 1 DFIFO Read/Write Access */
+
+/* Power and clock gating registers */
+
+#define STM32_OTGFS_PCGCCTL_OFFSET 0x0e00 /* Power and clock gating control register */
+
+/* Register Addresses *******************************************************************************/
+
+#define STM32_OTGFS_GOTGCTL (STM32_OTGFS_BASE+STM32_OTGFS_GOTGCTL_OFFSET)
+#define STM32_OTGFS_GOTGINT (STM32_OTGFS_BASE+STM32_OTGFS_GOTGINT_OFFSET)
+#define STM32_OTGFS_GAHBCFG (STM32_OTGFS_BASE+STM32_OTGFS_GAHBCFG_OFFSET)
+#define STM32_OTGFS_GUSBCFG (STM32_OTGFS_BASE+STM32_OTGFS_GUSBCFG_OFFSET)
+#define STM32_OTGFS_GRSTCTL (STM32_OTGFS_BASE+STM32_OTGFS_GRSTCTL_OFFSET)
+#define STM32_OTGFS_GINTSTS (STM32_OTGFS_BASE+STM32_OTGFS_GINTSTS_OFFSET)
+#define STM32_OTGFS_GINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_GINTMSK_OFFSET)
+#define STM32_OTGFS_GRXSTSR (STM32_OTGFS_BASE+STM32_OTGFS_GRXSTSR_OFFSET)
+#define STM32_OTGFS_GRXSTSP (STM32_OTGFS_BASE+STM32_OTGFS_GRXSTSP_OFFSET)
+#define STM32_OTGFS_GRXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_GRXFSIZ_OFFSET)
+#define STM32_OTGFS_HNPTXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_HNPTXFSIZ_OFFSET)
+#define STM32_OTGFS_DIEPTXF0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF0_OFFSET)
+#define STM32_OTGFS_HNPTXSTS (STM32_OTGFS_BASE+STM32_OTGFS_HNPTXSTS_OFFSET)
+#define STM32_OTGFS_GCCFG (STM32_OTGFS_BASE+STM32_OTGFS_GCCFG_OFFSET)
+#define STM32_OTGFS_CID (STM32_OTGFS_BASE+STM32_OTGFS_CID_OFFSET)
+#define STM32_OTGFS_HPTXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_HPTXFSIZ_OFFSET)
+
+#define STM32_OTGFS_DIEPTXF(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF_OFFSET(n))
+#define STM32_OTGFS_DIEPTXF1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF1_OFFSET)
+#define STM32_OTGFS_DIEPTXF2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF2_OFFSET)
+#define STM32_OTGFS_DIEPTXF3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF3_OFFSET)
+
+/* Host-mode control and status registers */
+
+#define STM32_OTGFS_HCFG (STM32_OTGFS_BASE+STM32_OTGFS_HCFG_OFFSET)
+#define STM32_OTGFS_HFIR (STM32_OTGFS_BASE+STM32_OTGFS_HFIR_OFFSET)
+#define STM32_OTGFS_HFNUM (STM32_OTGFS_BASE+STM32_OTGFS_HFNUM_OFFSET)
+#define STM32_OTGFS_HPTXSTS (STM32_OTGFS_BASE+STM32_OTGFS_HPTXSTS_OFFSET)
+#define STM32_OTGFS_HAINT (STM32_OTGFS_BASE+STM32_OTGFS_HAINT_OFFSET)
+#define STM32_OTGFS_HAINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_HAINTMSK_OFFSET)
+#define STM32_OTGFS_HPRT (STM32_OTGFS_BASE+STM32_OTGFS_HPRT_OFFSET)
+
+#define STM32_OTGFS_CHAN(n) (STM32_OTGFS_BASE+STM32_OTGFS_CHAN_OFFSET(n))
+
+#define STM32_OTGFS_HCCHAR(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR_OFFSET(n))
+#define STM32_OTGFS_HCCHAR0 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR0_OFFSET)
+#define STM32_OTGFS_HCCHAR1 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR1_OFFSET)
+#define STM32_OTGFS_HCCHAR2 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR2_OFFSET)
+#define STM32_OTGFS_HCCHAR3 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR3_OFFSET)
+#define STM32_OTGFS_HCCHAR4 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR4_OFFSET)
+#define STM32_OTGFS_HCCHAR5 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR5_OFFSET)
+#define STM32_OTGFS_HCCHAR6 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR6_OFFSET)
+#define STM32_OTGFS_HCCHAR7 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR7_OFFSET)
+
+#define STM32_OTGFS_HCINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCINT_OFFSET(n))
+#define STM32_OTGFS_HCINT0 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT0_OFFSET)
+#define STM32_OTGFS_HCINT1 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT1_OFFSET)
+#define STM32_OTGFS_HCINT2 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT2_OFFSET)
+#define STM32_OTGFS_HCINT3 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT3_OFFSET)
+#define STM32_OTGFS_HCINT4 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT4_OFFSET)
+#define STM32_OTGFS_HCINT5 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT5_OFFSET)
+#define STM32_OTGFS_HCINT6 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT6_OFFSET)
+#define STM32_OTGFS_HCINT7 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT7_OFFSET)
+
+#define STM32_OTGFS_HCINTMSK(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK_OFFSET(n))
+#define STM32_OTGFS_HCINTMSK0 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK0_OFFSET)
+#define STM32_OTGFS_HCINTMSK1 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK1_OFFSET)
+#define STM32_OTGFS_HCINTMSK2 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK2_OFFSET)
+#define STM32_OTGFS_HCINTMSK3 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK3_OFFSET)
+#define STM32_OTGFS_HCINTMSK4 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK4_OFFSET)
+#define STM32_OTGFS_HCINTMSK5 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK5_OFFSET)
+#define STM32_OTGFS_HCINTMSK6 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK6_OFFSET)
+#define STM32_OTGFS_HCINTMSK7 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK7_OFFSET)_
+
+#define STM32_OTGFS_HCTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ_OFFSET(n))
+#define STM32_OTGFS_HCTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ0_OFFSET)
+#define STM32_OTGFS_HCTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ1_OFFSET)
+#define STM32_OTGFS_HCTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ2_OFFSET)
+#define STM32_OTGFS_HCTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ3_OFFSET)
+#define STM32_OTGFS_HCTSIZ4 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ4_OFFSET)
+#define STM32_OTGFS_HCTSIZ5 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ5_OFFSET)
+#define STM32_OTGFS_HCTSIZ6 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ6_OFFSET)
+#define STM32_OTGFS_HCTSIZ7 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ7_OFFSET)
+
+/* Device-mode control and status registers */
+
+#define STM32_OTGFS_DCFG (STM32_OTGFS_BASE+STM32_OTGFS_DCFG_OFFSET)
+#define STM32_OTGFS_DCTL (STM32_OTGFS_BASE+STM32_OTGFS_DCTL_OFFSET)
+#define STM32_OTGFS_DSTS (STM32_OTGFS_BASE+STM32_OTGFS_DSTS_OFFSET)
+#define STM32_OTGFS_DIEPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DIEPMSK_OFFSET)
+#define STM32_OTGFS_DOEPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DOEPMSK_OFFSET)
+#define STM32_OTGFS_DAINT (STM32_OTGFS_BASE+STM32_OTGFS_DAINT_OFFSET)
+#define STM32_OTGFS_DAINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_DAINTMSK_OFFSET)
+#define STM32_OTGFS_DVBUSDIS (STM32_OTGFS_BASE+STM32_OTGFS_DVBUSDIS_OFFSET)
+#define STM32_OTGFS_DVBUSPULSE (STM32_OTGFS_BASE+STM32_OTGFS_DVBUSPULSE_OFFSET)
+#define STM32_OTGFS_DIEPEMPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DIEPEMPMSK_OFFSET)
+
+#define STM32_OTGFS_DIEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEP_OFFSET(n))
+
+#define STM32_OTGFS_DIEPCTL(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL_OFFSET(n))
+#define STM32_OTGFS_DIEPCTL0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL0_OFFSET)
+#define STM32_OTGFS_DIEPCTL1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL1_OFFSET)
+#define STM32_OTGFS_DIEPCTL2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL2_OFFSET)
+#define STM32_OTGFS_DIEPCTL3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL3_OFFSET)
+
+#define STM32_OTGFS_DIEPINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT_OFFSET(n))
+#define STM32_OTGFS_DIEPINT0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT0_OFFSET)
+#define STM32_OTGFS_DIEPINT1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT1_OFFSET)
+#define STM32_OTGFS_DIEPINT2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT2_OFFSET)
+#define STM32_OTGFS_DIEPINT3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT3_OFFSET)
+
+#define STM32_OTGFS_DIEPTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ_OFFSET(n))
+#define STM32_OTGFS_DIEPTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ0_OFFSET)
+#define STM32_OTGFS_DIEPTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ1_OFFSET)
+#define STM32_OTGFS_DIEPTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ2_OFFSET)
+#define STM32_OTGFS_DIEPTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ3_OFFSET)
+
+#define STM32_OTGFS_DTXFSTS(n) (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS_OFFSET(n))
+#define STM32_OTGFS_DTXFSTS0 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS0_OFFSET)
+#define STM32_OTGFS_DTXFSTS1 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS1_OFFSET)
+#define STM32_OTGFS_DTXFSTS2 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS2_OFFSET)
+#define STM32_OTGFS_DTXFSTS3 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS3_OFFSET)
+
+#define STM32_OTGFS_DOEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEP_OFFSET(n))
+
+#define STM32_OTGFS_DOEPCTL(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL_OFFSET(n))
+#define STM32_OTGFS_DOEPCTL0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL0_OFFSET)
+#define STM32_OTGFS_DOEPCTL1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL1_OFFSET)
+#define STM32_OTGFS_DOEPCTL2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL2_OFFSET)
+#define STM32_OTGFS_DOEPCTL3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL3_OFFSET)
+
+#define STM32_OTGFS_DOEPINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT_OFFSET(n))
+#define STM32_OTGFS_DOEPINT0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT0_OFFSET)
+#define STM32_OTGFS_DOEPINT1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT1_OFFSET)
+#define STM32_OTGFS_DOEPINT2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT2_OFFSET)
+#define STM32_OTGFS_DOEPINT3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT3_OFFSET)
+
+#define STM32_OTGFS_DOEPTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ_OFFSET(n))
+#define STM32_OTGFS_DOEPTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ0_OFFSET)
+#define STM32_OTGFS_DOEPTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ1_OFFSET)
+#define STM32_OTGFS_DOEPTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ2_OFFSET)
+#define STM32_OTGFS_DOEPTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ3_OFFSET)
+
+/* Data FIFO (DFIFO) access registers */
+
+#define STM32_OTGFS_DFIFO_DEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP_OFFSET(n))
+#define STM32_OTGFS_DFIFO_HCH(n) (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH_OFFSET(n))
+
+#define STM32_OTGFS_DFIFO_DEP0 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP0_OFFSET)
+#define STM32_OTGFS_DFIFO_HCH0 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH0_OFFSET)
+
+#define STM32_OTGFS_DFIFO_DEP1 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP1_OFFSET)
+#define STM32_OTGFS_DFIFO_HCH1 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH1_OFFSET)
+
+#define STM32_OTGFS_DFIFO_DEP2 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP2_OFFSET)
+#define STM32_OTGFS_DFIFO_HCH2 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH2_OFFSET)
+
+#define STM32_OTGFS_DFIFO_DEP3 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP3_OFFSET)
+#define STM32_OTGFS_DFIFO_HCH3 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH3_OFFSET)
+
+/* Power and clock gating registers */
+
+#define STM32_OTGFS_PCGCCTL (STM32_OTGFS_BASE+STM32_OTGFS_PCGCCTL_OFFSET)
+
+/* Register Bitfield Definitions ********************************************************************/
+/* Core global control and status registers */
+
+/* Control and status register */
+
+#define OTGFS_GOTGCTL_SRQSCS (1 << 0) /* Bit 0: Session request success */
+#define OTGFS_GOTGCTL_SRQ (1 << 1) /* Bit 1: Session request */
+ /* Bits 2-72 Reserved, must be kept at reset value */
+#define OTGFS_GOTGCTL_HNGSCS (1 << 8) /* Bit 8: Host negotiation success */
+#define OTGFS_GOTGCTL_HNPRQ (1 << 9) /* Bit 9: HNP request */
+#define OTGFS_GOTGCTL_HSHNPEN (1 << 10) /* Bit 10: host set HNP enable */
+#define OTGFS_GOTGCTL_DHNPEN (1 << 11) /* Bit 11: Device HNP enabled */
+ /* Bits 12-15: Reserved, must be kept at reset value */
+#define OTGFS_GOTGCTL_CIDSTS (1 << 16) /* Bit 16: Connector ID status */
+#define OTGFS_GOTGCTL_DBCT (1 << 17) /* Bit 17: Long/short debounce time */
+#define OTGFS_GOTGCTL_ASVLD (1 << 18) /* Bit 18: A-session valid */
+#define OTGFS_GOTGCTL_BSVLD (1 << 19) /* Bit 19: B-session valid */
+ /* Bits 20-31: Reserved, must be kept at reset value */
+/* Interrupt register */
+ /* Bits 1:0 Reserved, must be kept at reset value */
+#define OTGFS_GOTGINT_SEDET (1 << 2) /* Bit 2: Session end detected */
+ /* Bits 3-7: Reserved, must be kept at reset value */
+#define OTGFS_GOTGINT_SRSSCHG (1 << 8) /* Bit 8: Session request success status change */
+#define OTGFS_GOTGINT_HNSSCHG (1 << 9) /* Bit 9: Host negotiation success status change */
+ /* Bits 16:10 Reserved, must be kept at reset value */
+#define OTGFS_GOTGINT_HNGDET (1 << 17) /* Bit 17: Host negotiation detected */
+#define OTGFS_GOTGINT_ADTOCHG (1 << 18) /* Bit 18: A-device timeout change */
+#define OTGFS_GOTGINT_DBCDNE (1 << 19) /* Bit 19: Debounce done */
+ /* Bits 2-31: Reserved, must be kept at reset value */
+
+/* AHB configuration register */
+
+#define OTGFS_GAHBCFG_GINTMSK (1 << 0) /* Bit 0: Global interrupt mask */
+ /* Bits 1-6: Reserved, must be kept at reset value */
+#define OTGFS_GAHBCFG_TXFELVL (1 << 7) /* Bit 7: TxFIFO empty level */
+#define OTGFS_GAHBCFG_PTXFELVL (1 << 8) /* Bit 8: Periodic TxFIFO empty level */
+ /* Bits 20-31: Reserved, must be kept at reset value */
+/* USB configuration register */
+
+#define OTGFS_GUSBCFG_TOCAL_SHIFT (0) /* Bits 0-2: FS timeout calibration */
+#define OTGFS_GUSBCFG_TOCAL_MASK (7 << OTGFS_GUSBCFG_TOCAL_SHIFT)
+ /* Bits 3-6: Reserved, must be kept at reset value */
+#define OTGFS_GUSBCFG_SRPCAP (1 << 8) /* Bit 8: SRP-capable */
+#define OTGFS_GUSBCFG_HNPCAP (1 << 9) /* Bit 9: HNP-capable */
+#define OTGFS_GUSBCFG_TRDT_SHIFT (10) /* Bits 10-13: USB turnaround time */
+#define OTGFS_GUSBCFG_TRDT_MASK (15 << OTGFS_GUSBCFG_TRDT_SHIFT)
+# define OTGFS_GUSBCFG_TRDT(n) ((n) << OTGFS_GUSBCFG_TRDT_SHIFT)
+ /* Bits 14-28: Reserved, must be kept at reset value */
+#define OTGFS_GUSBCFG_FHMOD (1 << 29) /* Bit 29: Force host mode */
+#define OTGFS_GUSBCFG_FDMOD (1 << 30) /* Bit 30: Force device mode */
+#define OTGFS_GUSBCFG_CTXPKT (1 << 31) /* Bit 31: Corrupt Tx packet */
+ /* Bits 20-31: Reserved, must be kept at reset value */
+/* Reset register */
+
+#define OTGFS_GRSTCTL_CSRST (1 << 0) /* Bit 0: Core soft reset */
+#define OTGFS_GRSTCTL_HSRST (1 << 1) /* Bit 1: HCLK soft reset */
+#define OTGFS_GRSTCTL_FCRST (1 << 2) /* Bit 2: Host frame counter reset */
+ /* Bit 3 Reserved, must be kept at reset value */
+#define OTGFS_GRSTCTL_RXFFLSH (1 << 4) /* Bit 4: RxFIFO flush */
+#define OTGFS_GRSTCTL_TXFFLSH (1 << 5) /* Bit 5: TxFIFO flush */
+#define OTGFS_GRSTCTL_TXFNUM_SHIFT (10) /* Bits 6-10: TxFIFO number */
+#define OTGFS_GRSTCTL_TXFNUM_MASK (31 << OTGFS_GRSTCTL_TXFNUM_SHIFT)
+# define OTGFS_GRSTCTL_TXFNUM_HNONPER (0 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Non-periodic TxFIFO flush in host mode */
+# define OTGFS_GRSTCTL_TXFNUM_HPER (1 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Periodic TxFIFO flush in host mode */
+# define OTGFS_GRSTCTL_TXFNUM_HALL (16 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Flush all the transmit FIFOs in host mode.*/
+# define OTGFS_GRSTCTL_TXFNUM_D(n) ((n) << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* TXFIFO n flush in device mode, n=0-15 */
+# define OTGFS_GRSTCTL_TXFNUM_DALL (16 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Flush all the transmit FIFOs in device mode.*/
+ /* Bits 11-31: Reserved, must be kept at reset value */
+#define OTGFS_GRSTCTL_AHBIDL (1 << 31) /* Bit 31: AHB master idle */
+
+/* Core interrupt and Interrupt mask registers */
+
+#define OTGFS_GINTSTS_CMOD (1 << 0) /* Bit 0: Current mode of operation */
+# define OTGFS_GINTSTS_DEVMODE (0)
+# define OTGFS_GINTSTS_HOSTMODE (OTGFS_GINTSTS_CMOD)
+#define OTGFS_GINT_MMIS (1 << 1) /* Bit 1: Mode mismatch interrupt */
+#define OTGFS_GINT_OTG (1 << 2) /* Bit 2: OTG interrupt */
+#define OTGFS_GINT_SOF (1 << 3) /* Bit 3: Start of frame */
+#define OTGFS_GINT_RXFLVL (1 << 4) /* Bit 4: RxFIFO non-empty */
+#define OTGFS_GINT_NPTXFE (1 << 5) /* Bit 5: Non-periodic TxFIFO empty */
+#define OTGFS_GINT_GINAKEFF (1 << 6) /* Bit 6: Global IN non-periodic NAK effective */
+#define OTGFS_GINT_GONAKEFF (1 << 7) /* Bit 7: Global OUT NAK effective */
+ /* Bits 8-9: Reserved, must be kept at reset value */
+#define OTGFS_GINT_ESUSP (1 << 10) /* Bit 10: Early suspend */
+#define OTGFS_GINT_USBSUSP (1 << 11) /* Bit 11: USB suspend */
+#define OTGFS_GINT_USBRST (1 << 12) /* Bit 12: USB reset */
+#define OTGFS_GINT_ENUMDNE (1 << 13) /* Bit 13: Enumeration done */
+#define OTGFS_GINT_ISOODRP (1 << 14) /* Bit 14: Isochronous OUT packet dropped interrupt */
+#define OTGFS_GINT_EOPF (1 << 15) /* Bit 15: End of periodic frame interrupt */
+ /* Bits 16 Reserved, must be kept at reset value */
+#define OTGFS_GINTMSK_EPMISM (1 << 17) /* Bit 17: Endpoint mismatch interrupt mask */
+#define OTGFS_GINT_IEP (1 << 18) /* Bit 18: IN endpoint interrupt */
+#define OTGFS_GINT_OEP (1 << 19) /* Bit 19: OUT endpoint interrupt */
+#define OTGFS_GINT_IISOIXFR (1 << 20) /* Bit 20: Incomplete isochronous IN transfer */
+#define OTGFS_GINT_IISOOXFR (1 << 21) /* Bit 21: Incomplete isochronous OUT transfer */
+ /* Bits 22-23: Reserved, must be kept at reset value */
+#define OTGFS_GINT_HPRT (1 << 24) /* Bit 24: Host port interrupt */
+#define OTGFS_GINT_HC (1 << 25) /* Bit 25: Host channels interrupt */
+#define OTGFS_GINT_PTXFE (1 << 26) /* Bit 26: Periodic TxFIFO empty */
+ /* Bit 27 Reserved, must be kept at reset value */
+#define OTGFS_GINT_CIDSCHG (1 << 28) /* Bit 28: Connector ID status change */
+#define OTGFS_GINT_DISC (1 << 29) /* Bit 29: Disconnect detected interrupt */
+#define OTGFS_GINT_SRQ (1 << 30) /* Bit 30: Session request/new session detected interrupt */
+#define OTGFS_GINT_WKUP (1 << 31) /* Bit 31: Resume/remote wakeup detected interrupt */
+
+/* Receive status debug read/OTG status read and pop registers (host mode) */
+
+#define OTGFS_GRXSTSH_CHNUM_SHIFT (0) /* Bits 0-3: Channel number */
+#define OTGFS_GRXSTSH_CHNUM_MASK (15 << OTGFS_GRXSTSH_CHNUM_SHIFT)
+#define OTGFS_GRXSTSH_BCNT_SHIFT (4) /* Bits 4-14: Byte count */
+#define OTGFS_GRXSTSH_BCNT_MASK (0x7ff << OTGFS_GRXSTSH_BCNT_SHIFT)
+#define OTGFS_GRXSTSH_DPID_SHIFT (15) /* Bits 15-16: Data PID */
+#define OTGFS_GRXSTSH_DPID_MASK (3 << OTGFS_GRXSTSH_DPID_SHIFT)
+# define OTGFS_GRXSTSH_DPID_DATA0 (0 << OTGFS_GRXSTSH_DPID_SHIFT)
+# define OTGFS_GRXSTSH_DPID_DATA2 (1 << OTGFS_GRXSTSH_DPID_SHIFT)
+# define OTGFS_GRXSTSH_DPID_DATA1 (2 << OTGFS_GRXSTSH_DPID_SHIFT)
+# define OTGFS_GRXSTSH_DPID_MDATA (3 << OTGFS_GRXSTSH_DPID_SHIFT)
+#define OTGFS_GRXSTSH_PKTSTS_SHIFT (17) /* Bits 17-20: Packet status */
+#define OTGFS_GRXSTSH_PKTSTS_MASK (15 << OTGFS_GRXSTSH_PKTSTS_SHIFT)
+# define OTGFS_GRXSTSH_PKTSTS_INRECVD (2 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* IN data packet received */
+# define OTGFS_GRXSTSH_PKTSTS_INDONE (3 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* IN transfer completed */
+# define OTGFS_GRXSTSH_PKTSTS_DTOGERR (2 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* Data toggle error */
+# define OTGFS_GRXSTSH_PKTSTS_HALTED (7 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* Channel halted */
+ /* Bits 21-31: Reserved, must be kept at reset value */
+/* Receive status debug read/OTG status read and pop registers (device mode) */
+
+#define OTGFS_GRXSTSD_EPNUM_SHIFT (0) /* Bits 0-3: Endpoint number */
+#define OTGFS_GRXSTSD_EPNUM_MASK (15 << OTGFS_GRXSTSD_EPNUM_SHIFT)
+#define OTGFS_GRXSTSD_BCNT_SHIFT (4) /* Bits 4-14: Byte count */
+#define OTGFS_GRXSTSD_BCNT_MASK (0x7ff << OTGFS_GRXSTSD_BCNT_SHIFT)
+#define OTGFS_GRXSTSD_DPID_SHIFT (15) /* Bits 15-16: Data PID */
+#define OTGFS_GRXSTSD_DPID_MASK (3 << OTGFS_GRXSTSD_DPID_SHIFT)
+# define OTGFS_GRXSTSD_DPID_DATA0 (0 << OTGFS_GRXSTSD_DPID_SHIFT)
+# define OTGFS_GRXSTSD_DPID_DATA2 (1 << OTGFS_GRXSTSD_DPID_SHIFT)
+# define OTGFS_GRXSTSD_DPID_DATA1 (2 << OTGFS_GRXSTSD_DPID_SHIFT)
+# define OTGFS_GRXSTSD_DPID_MDATA (3 << OTGFS_GRXSTSD_DPID_SHIFT)
+#define OTGFS_GRXSTSD_PKTSTS_SHIFT (17) /* Bits 17-20: Packet status */
+#define OTGFS_GRXSTSD_PKTSTS_MASK (15 << OTGFS_GRXSTSD_PKTSTS_SHIFT)
+# define OTGFS_GRXSTSD_PKTSTS_OUTNAK (1 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* Global OUT NAK */
+# define OTGFS_GRXSTSD_PKTSTS_OUTRECVD (2 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* OUT data packet received */
+# define OTGFS_GRXSTSD_PKTSTS_OUTDONE (3 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* OUT transfer completed */
+# define OTGFS_GRXSTSD_PKTSTS_SETUPDONE (4 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* SETUP transaction completed */
+# define OTGFS_GRXSTSD_PKTSTS_SETUPRECVD (6 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* SETUP data packet received */
+#define OTGFS_GRXSTSD_FRMNUM_SHIFT (21) /* Bits 21-24: Frame number */
+#define OTGFS_GRXSTSD_FRMNUM_MASK (15 << OTGFS_GRXSTSD_FRMNUM_SHIFT)
+ /* Bits 25-31: Reserved, must be kept at reset value */
+/* Receive FIFO size register */
+
+#define OTGFS_GRXFSIZ_MASK (0xffff)
+
+/* Host non-periodic transmit FIFO size register */
+
+#define OTGFS_HNPTXFSIZ_NPTXFSA_SHIFT (0) /* Bits 0-15: Non-periodic transmit RAM start address */
+#define OTGFS_HNPTXFSIZ_NPTXFSA_MASK (0xffff << OTGFS_HNPTXFSIZ_NPTXFSA_SHIFT)
+#define OTGFS_HNPTXFSIZ_NPTXFD_SHIFT (16) /* Bits 16-31: Non-periodic TxFIFO depth */
+#define OTGFS_HNPTXFSIZ_NPTXFD_MASK (0xffff << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT)
+# define OTGFS_HNPTXFSIZ_NPTXFD_MIN (16 << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT)
+# define OTGFS_HNPTXFSIZ_NPTXFD_MAX (256 << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT)
+
+/* Endpoint 0 Transmit FIFO size */
+
+#define OTGFS_DIEPTXF0_TX0FD_SHIFT (0) /* Bits 0-15: Endpoint 0 transmit RAM start address */
+#define OTGFS_DIEPTXF0_TX0FD_MASK (0xffff << OTGFS_DIEPTXF0_TX0FD_SHIFT)
+#define OTGFS_DIEPTXF0_TX0FSA_SHIFT (16) /* Bits 16-31: Endpoint 0 TxFIFO depth */
+#define OTGFS_DIEPTXF0_TX0FSA_MASK (0xffff << OTGFS_DIEPTXF0_TX0FSA_SHIFT)
+# define OTGFS_DIEPTXF0_TX0FSA_MIN (16 << OTGFS_DIEPTXF0_TX0FSA_SHIFT)
+# define OTGFS_DIEPTXF0_TX0FSA_MAX (256 << OTGFS_DIEPTXF0_TX0FSA_SHIFT)
+
+/* Non-periodic transmit FIFO/queue status register */
+
+#define OTGFS_HNPTXSTS_NPTXFSAV_SHIFT (0) /* Bits 0-15: Non-periodic TxFIFO space available */
+#define OTGFS_HNPTXSTS_NPTXFSAV_MASK (0xffff << OTGFS_HNPTXSTS_NPTXFSAV_SHIFT)
+# define OTGFS_HNPTXSTS_NPTXFSAV_FULL (0 << OTGFS_HNPTXSTS_NPTXFSAV_SHIFT)
+#define OTGFS_HNPTXSTS_NPTQXSAV_SHIFT (16) /* Bits 16-23: Non-periodic transmit request queue space available */
+#define OTGFS_HNPTXSTS_NPTQXSAV_MASK (0xff << OTGFS_HNPTXSTS_NPTQXSAV_SHIFT)
+# define OTGFS_HNPTXSTS_NPTQXSAV_FULL (0 << OTGFS_HNPTXSTS_NPTQXSAV_SHIFT)
+#define OTGFS_HNPTXSTS_NPTXQTOP_SHIFT (24) /* Bits 24-30: Top of the non-periodic transmit request queue */
+#define OTGFS_HNPTXSTS_NPTXQTOP_MASK (0x7f << OTGFS_HNPTXSTS_NPTXQTOP_SHIFT)
+# define OTGFS_HNPTXSTS_TERMINATE (1 << 24) /* Bit 24: Terminate (last entry for selected channel/endpoint) */
+# define OTGFS_HNPTXSTS_TYPE_SHIFT (25) /* Bits 25-26: Status */
+# define OTGFS_HNPTXSTS_TYPE_MASK (3 << OTGFS_HNPTXSTS_TYPE_SHIFT)
+# define OTGFS_HNPTXSTS_TYPE_INOUT (0 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* IN/OUT token */
+# define OTGFS_HNPTXSTS_TYPE_ZLP (1 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* Zero-length transmit packet (device IN/host OUT) */
+# define OTGFS_HNPTXSTS_TYPE_HALT (3 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* Channel halt command */
+# define OTGFS_HNPTXSTS_CHNUM_SHIFT (27) /* Bits 27-30: Channel number */
+# define OTGFS_HNPTXSTS_CHNUM_MASK (15 << OTGFS_HNPTXSTS_CHNUM_SHIFT)
+# define OTGFS_HNPTXSTS_EPNUM_SHIFT (27) /* Bits 27-30: Endpoint number */
+# define OTGFS_HNPTXSTS_EPNUM_MASK (15 << OTGFS_HNPTXSTS_EPNUM_SHIFT)
+ /* Bit 31 Reserved, must be kept at reset value */
+/* general core configuration register */
+ /* Bits 15:0 Reserved, must be kept at reset value */
+#define OTGFS_GCCFG_PWRDWN (1 << 16) /* Bit 16: Power down */
+ /* Bit 17 Reserved, must be kept at reset value */
+#define OTGFS_GCCFG_VBUSASEN (1 << 18) /* Bit 18: Enable the VBUS sensing “A” device */
+#define OTGFS_GCCFG_VBUSBSEN (1 << 19) /* Bit 19: Enable the VBUS sensing “B” device */
+#define OTGFS_GCCFG_SOFOUTEN (1 << 20) /* Bit 20: SOF output enable */
+#define OTGFS_GCCFG_NOVBUSSENS (1 << 21) /* Bit 21: VBUS sensing disable option */
+ /* Bits 31:22 Reserved, must be kept at reset value */
+/* Core ID register (32-bit product ID) */
+
+/* Host periodic transmit FIFO size register */
+
+#define OTGFS_HPTXFSIZ_PTXSA_SHIFT (0) /* Bits 0-15: Host periodic TxFIFO start address */
+#define OTGFS_HPTXFSIZ_PTXSA_MASK (0xffff << OTGFS_HPTXFSIZ_PTXSA_SHIFT)
+#define OTGFS_HPTXFSIZ_PTXFD_SHIFT (16) /* Bits 16-31: Host periodic TxFIFO depth */
+#define OTGFS_HPTXFSIZ_PTXFD_MASK (0xffff << OTGFS_HPTXFSIZ_PTXFD_SHIFT)
+
+/* Device IN endpoint transmit FIFOn size register */
+
+#define OTGFS_DIEPTXF_INEPTXSA_SHIFT (0) /* Bits 0-15: IN endpoint FIFOx transmit RAM start address */
+#define OTGFS_DIEPTXF_INEPTXSA_MASK (0xffff << OTGFS_DIEPTXF_INEPTXSA_SHIFT)
+#define OTGFS_DIEPTXF_INEPTXFD_SHIFT (16) /* Bits 16-31: IN endpoint TxFIFO depth */
+#define OTGFS_DIEPTXF_INEPTXFD_MASK (0xffff << OTGFS_DIEPTXF_INEPTXFD_SHIFT)
+# define OTGFS_DIEPTXF_INEPTXFD_MIN (16 << OTGFS_DIEPTXF_INEPTXFD_MASK)
+
+/* Host-mode control and status registers */
+
+/* Host configuration register */
+
+#define OTGFS_HCFG_FSLSPCS_SHIFT (0) /* Bits 0-1: FS/LS PHY clock select */
+#define OTGFS_HCFG_FSLSPCS_MASK (3 << OTGFS_HCFG_FSLSPCS_SHIFT)
+# define OTGFS_HCFG_FSLSPCS_FS48MHz (1 << OTGFS_HCFG_FSLSPCS_SHIFT) /* FS host mode, PHY clock is running at 48 MHz */
+# define OTGFS_HCFG_FSLSPCS_LS48MHz (1 << OTGFS_HCFG_FSLSPCS_SHIFT) /* LS host mode, Select 48 MHz PHY clock frequency */
+# define OTGFS_HCFG_FSLSPCS_LS6MHz (2 << OTGFS_HCFG_FSLSPCS_SHIFT) /* LS host mode, Select 6 MHz PHY clock frequency */
+#define OTGFS_HCFG_FSLSS (1 << 2) /* Bit 2: FS- and LS-only support */
+ /* Bits 31:3 Reserved, must be kept at reset value */
+/* Host frame interval register */
+
+#define OTGFS_HFIR_MASK (0xffff)
+
+/* Host frame number/frame time remaining register */
+
+#define OTGFS_HFNUM_FRNUM_SHIFT (0) /* Bits 0-15: Frame number */
+#define OTGFS_HFNUM_FRNUM_MASK (0xffff << OTGFS_HFNUM_FRNUM_SHIFT)
+#define OTGFS_HFNUM_FTREM_SHIFT (16) /* Bits 16-31: Frame time remaining */
+#define OTGFS_HFNUM_FTREM_MASK (0xffff << OTGFS_HFNUM_FTREM_SHIFT)
+
+/* Host periodic transmit FIFO/queue status register */
+
+#define OTGFS_HPTXSTS_PTXFSAVL_SHIFT (0) /* Bits 0-15: Periodic transmit data FIFO space available */
+#define OTGFS_HPTXSTS_PTXFSAVL_MASK (0xffff << OTGFS_HPTXSTS_PTXFSAVL_SHIFT)
+# define OTGFS_HPTXSTS_PTXFSAVL_FULL (0 << OTGFS_HPTXSTS_PTXFSAVL_SHIFT)
+#define OTGFS_HPTXSTS_PTXQSAV_SHIFT (16) /* Bits 16-23: Periodic transmit request queue space available */
+#define OTGFS_HPTXSTS_PTXQSAV_MASK (0xff << OTGFS_HPTXSTS_PTXQSAV_SHIFT)
+# define OTGFS_HPTXSTS_PTXQSAV_FULL (0 << OTGFS_HPTXSTS_PTXQSAV_SHIFT)
+#define OTGFS_HPTXSTS_PTXQTOP_SHIFT (24) /* Bits 24-31: Top of the periodic transmit request queue */
+#define OTGFS_HPTXSTS_PTXQTOP_MASK (0x7f << OTGFS_HPTXSTS_PTXQTOP_SHIFT)
+# define OTGFS_HPTXSTS_TERMINATE (1 << 24) /* Bit 24: Terminate (last entry for selected channel/endpoint) */
+# define OTGFS_HPTXSTS_TYPE_SHIFT (25) /* Bits 25-26: Type */
+# define OTGFS_HPTXSTS_TYPE_MASK (3 << OTGFS_HPTXSTS_TYPE_SHIFT)
+# define OTGFS_HPTXSTS_TYPE_INOUT (0 << OTGFS_HPTXSTS_TYPE_SHIFT) /* IN/OUT token */
+# define OTGFS_HPTXSTS_TYPE_ZLP (1 << OTGFS_HPTXSTS_TYPE_SHIFT) /* Zero-length transmit packet */
+# define OTGFS_HPTXSTS_TYPE_HALT (3 << OTGFS_HPTXSTS_TYPE_SHIFT) /* Disable channel command */
+# define OTGFS_HPTXSTS_EPNUM_SHIFT (27) /* Bits 27-30: Endpoint number */
+# define OTGFS_HPTXSTS_EPNUM_MASK (15 << OTGFS_HPTXSTS_EPNUM_SHIFT)
+# define OTGFS_HPTXSTS_ODD (1 << 24) /* Bit 31: Send in odd (vs even) frame */
+
+/* Host all channels interrupt and all channels interrupt mask registers */
+
+#define OTGFS_HAINT(n) (1 << (n)) /* Bits 15:0 HAINTM: Channel interrupt */
+
+/* Host port control and status register */
+
+#define OTGFS_HPRT_PCSTS (1 << 0) /* Bit 0: Port connect status */
+#define OTGFS_HPRT_PCDET (1 << 1) /* Bit 1: Port connect detected */
+#define OTGFS_HPRT_PENA (1 << 2) /* Bit 2: Port enable */
+#define OTGFS_HPRT_PENCHNG (1 << 3) /* Bit 3: Port enable/disable change */
+#define OTGFS_HPRT_POCA (1 << 4) /* Bit 4: Port overcurrent active */
+#define OTGFS_HPRT_POCCHNG (1 << 5) /* Bit 5: Port overcurrent change */
+#define OTGFS_HPRT_PRES (1 << 6) /* Bit 6: Port resume */
+#define OTGFS_HPRT_PSUSP (1 << 7) /* Bit 7: Port suspend */
+#define OTGFS_HPRT_PRST (1 << 8) /* Bit 8: Port reset */
+ /* Bit 9: Reserved, must be kept at reset value */
+#define OTGFS_HPRT_PLSTS_SHIFT (10) /* Bits 10-11: Port line status */
+#define OTGFS_HPRT_PLSTS_MASK (3 << OTGFS_HPRT_PLSTS_SHIFT)
+# define OTGFS_HPRT_PLSTS_DP (1 << 10) /* Bit 10: Logic level of OTG_FS_FS_DP */
+# define OTGFS_HPRT_PLSTS_DM (1 << 11) /* Bit 11: Logic level of OTG_FS_FS_DM */
+#define OTGFS_HPRT_PPWR (1 << 12) /* Bit 12: Port power */
+#define OTGFS_HPRT_PTCTL_SHIFT (13) /* Bits 13-16: Port test control */
+#define OTGFS_HPRT_PTCTL_MASK (15 << OTGFS_HPRT_PTCTL_SHIFT)
+# define OTGFS_HPRT_PTCTL_DISABLED (0 << OTGFS_HPRT_PTCTL_SHIFT) /* Test mode disabled */
+# define OTGFS_HPRT_PTCTL_J (1 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_J mode */
+# define OTGFS_HPRT_PTCTL_L (2 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_K mode */
+# define OTGFS_HPRT_PTCTL_SE0_NAK (3 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_SE0_NAK mode */
+# define OTGFS_HPRT_PTCTL_PACKET (4 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_Packet mode */
+# define OTGFS_HPRT_PTCTL_FORCE (5 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_Force_Enable */
+#define OTGFS_HPRT_PSPD_SHIFT (17) /* Bits 17-18: Port speed */
+#define OTGFS_HPRT_PSPD_MASK (3 << OTGFS_HPRT_PSPD_SHIFT)
+# define OTGFS_HPRT_PSPD_FS (1 << OTGFS_HPRT_PSPD_SHIFT) /* Full speed */
+# define OTGFS_HPRT_PSPD_LS (2 << OTGFS_HPRT_PSPD_SHIFT) /* Low speed */
+ /* Bits 19-31: Reserved, must be kept at reset value */
+
+/* Host channel-n characteristics register */
+
+#define OTGFS_HCCHAR0_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */
+#define OTGFS_HCCHAR_MPSIZ_MASK (0x7ff << OTGFS_HCCHAR_MPSIZ_SHIFT)
+#define OTGFS_HCCHAR_EPNUM_SHIFT (11) /* Bits 11-14: Endpoint number */
+#define OTGFS_HCCHAR_EPNUM_MASK (15 << OTGFS_HCCHAR_EPNUM_SHIFT)
+#define OTGFS_HCCHAR_EPDIR (1 << 15) /* Bit 15: Endpoint direction */
+# define OTGFS_HCCHAR_EPDIR_OUT (0)
+# define OTGFS_HCCHAR_EPDIR_IN OTGFS_HCCHAR_EPDIR
+ /* Bit 16 Reserved, must be kept at reset value */
+#define OTGFS_HCCHAR_LSDEV (1 << 17) /* Bit 17: Low-speed device */
+#define OTGFS_HCCHAR_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */
+#define OTGFS_HCCHAR_EPTYP_MASK (3 << OTGFS_HCCHAR_EPTYP_SHIFT)
+# define OTGFS_HCCHAR_EPTYP_CTRL (0 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Control */
+# define OTGFS_HCCHAR_EPTYP_ISOC (1 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Isochronous */
+# define OTGFS_HCCHAR_EPTYP_BULK (2 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Bulk */
+# define OTGFS_HCCHAR_EPTYP_INTR (3 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Interrupt */
+#define OTGFS_HCCHAR_MCNT_SHIFT (20) /* Bits 20-21: Multicount */
+#define OTGFS_HCCHAR_MCNT_MASK (3 << OTGFS_HCCHAR_MCNT_SHIFT)
+#define OTGFS_HCCHAR_DAD_SHIFT (22) /* Bits 22-28: Device address */
+#define OTGFS_HCCHAR_DAD_MASK (0x7f << OTGFS_HCCHAR_DAD_SHIFT)
+#define OTGFS_HCCHAR_ODDFRM (1 << 29) /* Bit 29: Odd frame */
+#define OTGFS_HCCHAR_CHDIS (1 << 30) /* Bit 30: Channel disable */
+#define OTGFS_HCCHAR_CHENA (1 << 31) /* Bit 31: Channel enable */
+
+/* Host channel-n interrupt and Host channel-0 interrupt mask registers */
+
+#define OTGFS_HCINT_XFRC (1 << 0) /* Bit 0: Transfer completed */
+#define OTGFS_HCINT_CHH (1 << 1) /* Bit 1: Channel halted */
+ /* Bit 2: Reserved, must be kept at reset value */
+#define OTGFS_HCINT_STALL (1 << 3) /* Bit 3: STALL response received interrupt */
+#define OTGFS_HCINT_NAK (1 << 4) /* Bit 4: NAK response received interrupt */
+#define OTGFS_HCINT_ACK (1 << 5) /* Bit 5: ACK response received/transmitted interrupt */
+#define OTGFS_HCINTMSK_NYET (1 << 6) /* Bit 6: response received interrupt mask */
+#define OTGFS_HCINT_TXERR (1 << 7) /* Bit 7: Transaction error */
+#define OTGFS_HCINT_BBERR (1 << 8) /* Bit 8: Babble error */
+#define OTGFS_HCINT_FRMOR (1 << 9) /* Bit 9: Frame overrun */
+#define OTGFS_HCINT_DTERR (1 << 10) /* Bit 10: Data toggle error */
+ /* Bits 11-31 Reserved, must be kept at reset value */
+/* Host channel-n interrupt register */
+
+#define OTGFS_HCTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */
+#define OTGFS_HCTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_HCTSIZ_XFRSIZ_SHIFT)
+#define OTGFS_HCTSIZ_PKTCNT_SHIFT (19) /* Bits 19-28: Packet count */
+#define OTGFS_HCTSIZ_PKTCNT_MASK (0x3ff << OTGFS_HCTSIZ_PKTCNT_SHIFT)
+#define OTGFS_HCTSIZ_DPID_SHIFT (29) /* Bits 29-30: Data PID */
+#define OTGFS_HCTSIZ_DPID_MASK (3 << OTGFS_HCTSIZ_DPID_SHIFT)
+# define OTGFS_HCTSIZ_DPID_DATA0 (0 << OTGFS_HCTSIZ_DPID_SHIFT)
+# define OTGFS_HCTSIZ_DPID_DATA2 (1 << OTGFS_HCTSIZ_DPID_SHIFT)
+# define OTGFS_HCTSIZ_DPID_DATA1 (2 << OTGFS_HCTSIZ_DPID_SHIFT)
+# define OTGFS_HCTSIZ_DPID_MDATA (3 << OTGFS_HCTSIZ_DPID_SHIFT)
+ /* Bit 31 Reserved, must be kept at reset value */
+/* Device-mode control and status registers */
+
+/* Device configuration register */
+
+#define OTGFS_DCFG_DSPD_SHIFT (0) /* Bits 0-1: Device speed */
+#define OTGFS_DCFG_DSPD_MASK (3 << OTGFS_DCFG_DSPD_SHIFT)
+# define OTGFS_DCFG_DSPD_FS (3 << OTGFS_DCFG_DSPD_SHIFT) /* Full speed */
+#define OTGFS_DCFG_NZLSOHSK (1 << 2) /* Bit 2: Non-zero-length status OUT handshake */
+ /* Bit 3: Reserved, must be kept at reset value */
+#define OTGFS_DCFG_DAD_SHIFT (4) /* Bits 4-10: Device address */
+#define OTGFS_DCFG_DAD_MASK (0x7f << OTGFS_DCFG_DAD_SHIFT)
+#define OTGFS_DCFG_PFIVL_SHIFT (11) /* Bits 11-12: Periodic frame interval */
+#define OTGFS_DCFG_PFIVL_MASK (3 << OTGFS_DCFG_PFIVL_SHIFT)
+# define OTGFS_DCFG_PFIVL_80PCT (0 << OTGFS_DCFG_PFIVL_SHIFT) /* 80% of the frame interval */
+# define OTGFS_DCFG_PFIVL_85PCT (1 << OTGFS_DCFG_PFIVL_SHIFT) /* 85% of the frame interval */
+# define OTGFS_DCFG_PFIVL_90PCT (2 << OTGFS_DCFG_PFIVL_SHIFT) /* 90% of the frame interval */
+# define OTGFS_DCFG_PFIVL_95PCT (3 << OTGFS_DCFG_PFIVL_SHIFT) /* 95% of the frame interval */
+ /* Bits 13-31 Reserved, must be kept at reset value */
+/* Device control register */
+
+#define OTGFS_TESTMODE_DISABLED (0) /* Test mode disabled */
+#define OTGFS_TESTMODE_J (1) /* Test_J mode */
+#define OTGFS_TESTMODE_K (2) /* Test_K mode */
+#define OTGFS_TESTMODE_SE0_NAK (3) /* Test_SE0_NAK mode */
+#define OTGFS_TESTMODE_PACKET (4) /* Test_Packet mode */
+#define OTGFS_TESTMODE_FORCE (5) /* Test_Force_Enable */
+
+#define OTGFS_DCTL_RWUSIG (1 << 0) /* Bit 0: Remote wakeup signaling */
+#define OTGFS_DCTL_SDIS (1 << 1) /* Bit 1: Soft disconnect */
+#define OTGFS_DCTL_GINSTS (1 << 2) /* Bit 2: Global IN NAK status */
+#define OTGFS_DCTL_GONSTS (1 << 3) /* Bit 3: Global OUT NAK status */
+#define OTGFS_DCTL_TCTL_SHIFT (4) /* Bits 4-6: Test control */
+#define OTGFS_DCTL_TCTL_MASK (7 << OTGFS_DCTL_TCTL_SHIFT)
+# define OTGFS_DCTL_TCTL_DISABLED (0 << OTGFS_DCTL_TCTL_SHIFT) /* Test mode disabled */
+# define OTGFS_DCTL_TCTL_J (1 << OTGFS_DCTL_TCTL_SHIFT) /* Test_J mode */
+# define OTGFS_DCTL_TCTL_K (2 << OTGFS_DCTL_TCTL_SHIFT) /* Test_K mode */
+# define OTGFS_DCTL_TCTL_SE0_NAK (3 << OTGFS_DCTL_TCTL_SHIFT) /* Test_SE0_NAK mode */
+# define OTGFS_DCTL_TCTL_PACKET (4 << OTGFS_DCTL_TCTL_SHIFT) /* Test_Packet mode */
+# define OTGFS_DCTL_TCTL_FORCE (5 << OTGFS_DCTL_TCTL_SHIFT) /* Test_Force_Enable */
+#define OTGFS_DCTL_SGINAK (1 << 7) /* Bit 7: Set global IN NAK */
+#define OTGFS_DCTL_CGINAK (1 << 8) /* Bit 8: Clear global IN NAK */
+#define OTGFS_DCTL_SGONAK (1 << 9) /* Bit 9: Set global OUT NAK */
+#define OTGFS_DCTL_CGONAK (1 << 10) /* Bit 10: Clear global OUT NAK */
+#define OTGFS_DCTL_POPRGDNE (1 << 11) /* Bit 11: Power-on programming done */
+ /* Bits 12-31: Reserved, must be kept at reset value */
+/* Device status register */
+
+#define OTGFS_DSTS_SUSPSTS (1 << 0) /* Bit 0: Suspend status */
+#define OTGFS_DSTS_ENUMSPD_SHIFT (1) /* Bits 1-2: Enumerated speed */
+#define OTGFS_DSTS_ENUMSPD_MASK (3 << OTGFS_DSTS_ENUMSPD_SHIFT)
+# define OTGFS_DSTS_ENUMSPD_FS (3 << OTGFS_DSTS_ENUMSPD_MASK) /* Full speed */
+ /* Bits 4-7: Reserved, must be kept at reset value */
+#define OTGFS_DSTS_EERR (1 << 3) /* Bit 3: Erratic error */
+#define OTGFS_DSTS_SOFFN_SHIFT (8) /* Bits 8-21: Frame number of the received SOF */
+#define OTGFS_DSTS_SOFFN_MASK (0x3fff << OTGFS_DSTS_SOFFN_SHIFT)
+#define OTGFS_DSTS_SOFFN0 (1 << 8) /* Bits 8: Frame number even/odd bit */
+#define OTGFS_DSTS_SOFFN_EVEN 0
+#define OTGFS_DSTS_SOFFN_ODD OTGFS_DSTS_SOFFN0
+ /* Bits 22-31: Reserved, must be kept at reset value */
+/* Device IN endpoint common interrupt mask register */
+
+#define OTGFS_DIEPMSK_XFRCM (1 << 0) /* Bit 0: Transfer completed interrupt mask */
+#define OTGFS_DIEPMSK_EPDM (1 << 1) /* Bit 1: Endpoint disabled interrupt mask */
+ /* Bit 2: Reserved, must be kept at reset value */
+#define OTGFS_DIEPMSK_TOM (1 << 3) /* Bit 3: Timeout condition mask (Non-isochronous endpoints) */
+#define OTGFS_DIEPMSK_ITTXFEMSK (1 << 4) /* Bit 4: IN token received when TxFIFO empty mask */
+#define OTGFS_DIEPMSK_INEPNMM (1 << 5) /* Bit 5: IN token received with EP mismatch mask */
+#define OTGFS_DIEPMSK_INEPNEM (1 << 6) /* Bit 6: IN endpoint NAK effective mask */
+ /* Bits 7-31: Reserved, must be kept at reset value */
+/* Device OUT endpoint common interrupt mask register */
+
+#define OTGFS_DOEPMSK_XFRCM (1 << 0) /* Bit 0: Transfer completed interrupt mask */
+#define OTGFS_DOEPMSK_EPDM (1 << 1) /* Bit 1: Endpoint disabled interrupt mask */
+ /* Bit 2: Reserved, must be kept at reset value */
+#define OTGFS_DOEPMSK_STUPM (1 << 3) /* Bit 3: SETUP phase done mask */
+#define OTGFS_DOEPMSK_OTEPDM (1 << 4) /* Bit 4: OUT token received when endpoint disabled mask */
+ /* Bits 5-31: Reserved, must be kept at reset value */
+/* Device all endpoints interrupt and All endpoints interrupt mask registers */
+
+#define OTGFS_DAINT_IEP_SHIFT (0) /* Bits 0-15: IN endpoint interrupt bits */
+#define OTGFS_DAINT_IEP_MASK (0xffff << OTGFS_DAINT_IEP_SHIFT)
+# define OTGFS_DAINT_IEP(n) (1 << (n))
+#define OTGFS_DAINT_OEP_SHIFT (16) /* Bits 16-31: OUT endpoint interrupt bits */
+#define OTGFS_DAINT_OEP_MASK (0xffff << OTGFS_DAINT_OEP_SHIFT)
+# define OTGFS_DAINT_OEP(n) (1 << ((n)+16))
+
+/* Device VBUS discharge time register */
+
+#define OTGFS_DVBUSDIS_MASK (0xffff)
+
+/* Device VBUS pulsing time register */
+
+#define OTGFS_DVBUSPULSE_MASK (0xfff)
+
+/* Device IN endpoint FIFO empty interrupt mask register */
+
+#define OTGFS_DIEPEMPMSK(n) (1 << (n))
+
+/* Device control IN endpoint 0 control register */
+
+#define OTGFS_DIEPCTL0_MPSIZ_SHIFT (0) /* Bits 0-1: Maximum packet size */
+#define OTGFS_DIEPCTL0_MPSIZ_MASK (3 << OTGFS_DIEPCTL0_MPSIZ_SHIFT)
+# define OTGFS_DIEPCTL0_MPSIZ_64 (0 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 64 bytes */
+# define OTGFS_DIEPCTL0_MPSIZ_32 (1 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 32 bytes */
+# define OTGFS_DIEPCTL0_MPSIZ_16 (2 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 16 bytes */
+# define OTGFS_DIEPCTL0_MPSIZ_8 (3 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 8 bytes */
+ /* Bits 2-14: Reserved, must be kept at reset value */
+#define OTGFS_DIEPCTL0_USBAEP (1 << 15) /* Bit 15: USB active endpoint */
+ /* Bit 16: Reserved, must be kept at reset value */
+#define OTGFS_DIEPCTL0_NAKSTS (1 << 17) /* Bit 17: NAK status */
+#define OTGFS_DIEPCTL0_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */
+#define OTGFS_DIEPCTL0_EPTYP_MASK (3 << OTGFS_DIEPCTL0_EPTYP_SHIFT)
+# define OTGFS_DIEPCTL0_EPTYP_CTRL (0 << OTGFS_DIEPCTL0_EPTYP_SHIFT) /* Control (hard-coded) */
+ /* Bit 20: Reserved, must be kept at reset value */
+#define OTGFS_DIEPCTL0_STALL (1 << 21) /* Bit 21: STALL handshake */
+#define OTGFS_DIEPCTL0_TXFNUM_SHIFT (22) /* Bits 22-25: TxFIFO number */
+#define OTGFS_DIEPCTL0_TXFNUM_MASK (15 << OTGFS_DIEPCTL0_TXFNUM_SHIFT)
+#define OTGFS_DIEPCTL0_CNAK (1 << 26) /* Bit 26: Clear NAK */
+#define OTGFS_DIEPCTL0_SNAK (1 << 27) /* Bit 27: Set NAK */
+ /* Bits 28-29: Reserved, must be kept at reset value */
+#define OTGFS_DIEPCTL0_EPDIS (1 << 30) /* Bit 30: Endpoint disable */
+#define OTGFS_DIEPCTL0_EPENA (1 << 31) /* Bit 31: Endpoint enable */
+
+/* Device control IN endpoint n control register */
+
+#define OTGFS_DIEPCTL_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */
+#define OTGFS_DIEPCTL_MPSIZ_MASK (0x7ff << OTGFS_DIEPCTL_MPSIZ_SHIFT)
+ /* Bits 11-14: Reserved, must be kept at reset value */
+#define OTGFS_DIEPCTL_USBAEP (1 << 15) /* Bit 15: USB active endpoint */
+#define OTGFS_DIEPCTL_EONUM (1 << 16) /* Bit 16: Even/odd frame */
+# define OTGFS_DIEPCTL_EVEN (0)
+# define OTGFS_DIEPCTL_ODD OTGFS_DIEPCTL_EONUM
+# define OTGFS_DIEPCTL_DATA0 (0)
+# define OTGFS_DIEPCTL_DATA1 OTGFS_DIEPCTL_EONUM
+#define OTGFS_DIEPCTL_NAKSTS (1 << 17) /* Bit 17: NAK status */
+#define OTGFS_DIEPCTL_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */
+#define OTGFS_DIEPCTL_EPTYP_MASK (3 << OTGFS_DIEPCTL_EPTYP_SHIFT)
+# define OTGFS_DIEPCTL_EPTYP_CTRL (0 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Control */
+# define OTGFS_DIEPCTL_EPTYP_ISOC (1 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Isochronous */
+# define OTGFS_DIEPCTL_EPTYP_BULK (2 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Bulk */
+# define OTGFS_DIEPCTL_EPTYP_INTR (3 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Interrupt */
+ /* Bit 20: Reserved, must be kept at reset value */
+#define OTGFS_DIEPCTL_STALL (1 << 21) /* Bit 21: STALL handshake */
+#define OTGFS_DIEPCTL_TXFNUM_SHIFT (22) /* Bits 22-25: TxFIFO number */
+#define OTGFS_DIEPCTL_TXFNUM_MASK (15 << OTGFS_DIEPCTL_TXFNUM_SHIFT)
+#define OTGFS_DIEPCTL_CNAK (1 << 26) /* Bit 26: Clear NAK */
+#define OTGFS_DIEPCTL_SNAK (1 << 27) /* Bit 27: Set NAK */
+#define OTGFS_DIEPCTL_SD0PID (1 << 28) /* Bit 28: Set DATA0 PID (interrupt/bulk) */
+#define OTGFS_DIEPCTL_SEVNFRM (1 << 28) /* Bit 28: Set even frame (isochronous)) */
+#define OTGFS_DIEPCTL_SODDFRM (1 << 29) /* Bit 29: Set odd frame (isochronous) */
+#define OTGFS_DIEPCTL_EPDIS (1 << 30) /* Bit 30: Endpoint disable */
+#define OTGFS_DIEPCTL_EPENA (1 << 31) /* Bit 31: Endpoint enable */
+
+/* Device endpoint-n interrupt register */
+
+#define OTGFS_DIEPINT_XFRC (1 << 0) /* Bit 0: Transfer completed interrupt */
+#define OTGFS_DIEPINT_EPDISD (1 << 1) /* Bit 1: Endpoint disabled interrupt */
+ /* Bit 2: Reserved, must be kept at reset value */
+#define OTGFS_DIEPINT_TOC (1 << 3) /* Bit 3: Timeout condition */
+#define OTGFS_DIEPINT_ITTXFE (1 << 4) /* Bit 4: IN token received when TxFIFO is empty */
+ /* Bit 5: Reserved, must be kept at reset value */
+#define OTGFS_DIEPINT_INEPNE (1 << 6) /* Bit 6: IN endpoint NAK effective */
+#define OTGFS_DIEPINT_TXFE (1 << 7) /* Bit 7: Transmit FIFO empty */
+ /* Bits 8-31: Reserved, must be kept at reset value */
+/* Device IN endpoint 0 transfer size register */
+
+#define OTGFS_DIEPTSIZ0_XFRSIZ_SHIFT (0) /* Bits 0-6: Transfer size */
+#define OTGFS_DIEPTSIZ0_XFRSIZ_MASK (0x7f << OTGFS_DIEPTSIZ0_XFRSIZ_SHIFT)
+ /* Bits 7-18: Reserved, must be kept at reset value */
+#define OTGFS_DIEPTSIZ0_PKTCNT_SHIFT (19) /* Bits 19-20: Packet count */
+#define OTGFS_DIEPTSIZ0_PKTCNT_MASK (3 << OTGFS_DIEPTSIZ0_PKTCNT_SHIFT)
+ /* Bits 21-31: Reserved, must be kept at reset value */
+/* Device IN endpoint n transfer size register */
+
+#define OTGFS_DIEPTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */
+#define OTGFS_DIEPTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_DIEPTSIZ_XFRSIZ_SHIFT)
+#define OTGFS_DIEPTSIZ_PKTCNT_SHIFT (19) /* Bit 19-28: Packet count */
+#define OTGFS_DIEPTSIZ_PKTCNT_MASK (0x3ff << OTGFS_DIEPTSIZ_PKTCNT_SHIFT)
+#define OTGFS_DIEPTSIZ_MCNT_SHIFT (29) /* Bits 29-30: Multi count */
+#define OTGFS_DIEPTSIZ_MCNT_MASK (3 << OTGFS_DIEPTSIZ_MCNT_SHIFT)
+ /* Bit 31: Reserved, must be kept at reset value */
+/* Device OUT endpoint TxFIFO status register */
+
+#define OTGFS_DTXFSTS_MASK (0xffff)
+
+/* Device OUT endpoint 0 control register */
+
+#define OTGFS_DOEPCTL0_MPSIZ_SHIFT (0) /* Bits 0-1: Maximum packet size */
+#define OTGFS_DOEPCTL0_MPSIZ_MASK (3 << OTGFS_DOEPCTL0_MPSIZ_SHIFT)
+# define OTGFS_DOEPCTL0_MPSIZ_64 (0 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 64 bytes */
+# define OTGFS_DOEPCTL0_MPSIZ_32 (1 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 32 bytes */
+# define OTGFS_DOEPCTL0_MPSIZ_16 (2 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 16 bytes */
+# define OTGFS_DOEPCTL0_MPSIZ_8 (3 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 8 bytes */
+ /* Bits 2-14: Reserved, must be kept at reset value */
+#define OTGFS_DOEPCTL0_USBAEP (1 << 15) /* Bit 15: USB active endpoint */
+ /* Bit 16: Reserved, must be kept at reset value */
+#define OTGFS_DOEPCTL0_NAKSTS (1 << 17) /* Bit 17: NAK status */
+#define OTGFS_DOEPCTL0_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */
+#define OTGFS_DOEPCTL0_EPTYP_MASK (3 << OTGFS_DOEPCTL0_EPTYP_SHIFT)
+# define OTGFS_DOEPCTL0_EPTYP_CTRL (0 << OTGFS_DOEPCTL0_EPTYP_SHIFT) /* Control (hard-coded) */
+#define OTGFS_DOEPCTL0_SNPM (1 << 20) /* Bit 20: Snoop mode */
+#define OTGFS_DOEPCTL0_STALL (1 << 21) /* Bit 21: STALL handshake */
+ /* Bits 22-25: Reserved, must be kept at reset value */
+#define OTGFS_DOEPCTL0_CNAK (1 << 26) /* Bit 26: Clear NAK */
+#define OTGFS_DOEPCTL0_SNAK (1 << 27) /* Bit 27: Set NAK */
+ /* Bits 28-29: Reserved, must be kept at reset value */
+#define OTGFS_DOEPCTL0_EPDIS (1 << 30) /* Bit 30: Endpoint disable */
+#define OTGFS_DOEPCTL0_EPENA (1 << 31) /* Bit 31: Endpoint enable */
+
+/* Device OUT endpoint n control register */
+
+#define OTGFS_DOEPCTL_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */
+#define OTGFS_DOEPCTL_MPSIZ_MASK (0x7ff << OTGFS_DOEPCTL_MPSIZ_SHIFT)
+ /* Bits 11-14: Reserved, must be kept at reset value */
+#define OTGFS_DOEPCTL_USBAEP (1 << 15) /* Bit 15: USB active endpoint */
+#define OTGFS_DOEPCTL_DPID (1 << 16) /* Bit 16: Endpoint data PID (interrupt/buld) */
+# define OTGFS_DOEPCTL_DATA0 (0)
+# define OTGFS_DOEPCTL_DATA1 OTGFS_DOEPCTL_DPID
+#define OTGFS_DOEPCTL_EONUM (1 << 16) /* Bit 16: Even/odd frame (isochronous) */
+# define OTGFS_DOEPCTL_EVEN (0)
+# define OTGFS_DOEPCTL_ODD OTGFS_DOEPCTL_EONUM
+#define OTGFS_DOEPCTL_NAKSTS (1 << 17) /* Bit 17: NAK status */
+#define OTGFS_DOEPCTL_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */
+#define OTGFS_DOEPCTL_EPTYP_MASK (3 << OTGFS_DOEPCTL_EPTYP_SHIFT)
+# define OTGFS_DOEPCTL_EPTYP_CTRL (0 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Control */
+# define OTGFS_DOEPCTL_EPTYP_ISOC (1 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Isochronous */
+# define OTGFS_DOEPCTL_EPTYP_BULK (2 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Bulk */
+# define OTGFS_DOEPCTL_EPTYP_INTR (3 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Interrupt */
+#define OTGFS_DOEPCTL_SNPM (1 << 20) /* Bit 20: Snoop mode */
+#define OTGFS_DOEPCTL_STALL (1 << 21) /* Bit 21: STALL handshake */
+ /* Bits 22-25: Reserved, must be kept at reset value */
+#define OTGFS_DOEPCTL_CNAK (1 << 26) /* Bit 26: Clear NAK */
+#define OTGFS_DOEPCTL_SNAK (1 << 27) /* Bit 27: Set NAK */
+#define OTGFS_DOEPCTL_SD0PID (1 << 28) /* Bit 28: Set DATA0 PID (interrupt/bulk) */
+#define OTGFS_DOEPCTL_SEVNFRM (1 << 28) /* Bit 28: Set even frame (isochronous) */
+#define OTGFS_DOEPCTL_SD1PID (1 << 29) /* Bit 29: Set DATA1 PID (interrupt/bulk) */
+#define OTGFS_DOEPCTL_SODDFRM (1 << 29) /* Bit 29: Set odd frame (isochronous */
+#define OTGFS_DOEPCTL_EPDIS (1 << 30) /* Bit 30: Endpoint disable */
+#define OTGFS_DOEPCTL_EPENA (1 << 31) /* Bit 31: Endpoint enable */
+
+/* Device endpoint-n interrupt register */
+
+#define OTGFS_DOEPINT_XFRC (1 << 0) /* Bit 0: Transfer completed interrupt */
+#define OTGFS_DOEPINT_EPDISD (1 << 1) /* Bit 1: Endpoint disabled interrupt */
+ /* Bit 2: Reserved, must be kept at reset value */
+#define OTGFS_DOEPINT_SETUP (1 << 3) /* Bit 3: SETUP phase done */
+#define OTGFS_DOEPINT_OTEPDIS (1 << 4) /* Bit 4: OUT token received when endpoint disabled */
+ /* Bit 5: Reserved, must be kept at reset value */
+#define OTGFS_DOEPINT_B2BSTUP (1 << 6) /* Bit 6: Back-to-back SETUP packets received */
+ /* Bits 7-31: Reserved, must be kept at reset value */
+/* Device OUT endpoint-0 transfer size register */
+
+#define OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT (0) /* Bits 0-6: Transfer size */
+#define OTGFS_DOEPTSIZ0_XFRSIZ_MASK (0x7f << OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT)
+ /* Bits 7-18: Reserved, must be kept at reset value */
+#define OTGFS_DOEPTSIZ0_PKTCNT (1 << 19) /* Bit 19 PKTCNT: Packet count */
+ /* Bits 20-28: Reserved, must be kept at reset value */
+#define OTGFS_DOEPTSIZ0_STUPCNT_SHIFT (29) /* Bits 29-30: SETUP packet count */
+#define OTGFS_DOEPTSIZ0_STUPCNT_MASK (3 << OTGFS_DOEPTSIZ0_STUPCNT_SHIFT)
+ /* Bit 31: Reserved, must be kept at reset value */
+/* Device OUT endpoint-n transfer size register */
+
+#define OTGFS_DOEPTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */
+#define OTGFS_DOEPTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_DOEPTSIZ_XFRSIZ_SHIFT)
+#define OTGFS_DOEPTSIZ_PKTCNT_SHIFT (19) /* Bit 19-28: Packet count */
+#define OTGFS_DOEPTSIZ_PKTCNT_MASK (0x3ff << OTGFS_DOEPTSIZ_PKTCNT_SHIFT)
+#define OTGFS_DOEPTSIZ_STUPCNT_SHIFT (29) /* Bits 29-30: SETUP packet count */
+#define OTGFS_DOEPTSIZ_STUPCNT_MASK (3 << OTGFS_DOEPTSIZ_STUPCNT_SHIFT)
+#define OTGFS_DOEPTSIZ_RXDPID_SHIFT (29) /* Bits 29-30: Received data PID */
+#define OTGFS_DOEPTSIZ_RXDPID_MASK (3 << OTGFS_DOEPTSIZ_RXDPID_SHIFT)
+# define OTGFS_DOEPTSIZ_RXDPID_DATA0 (0 << OTGFS_DOEPTSIZ_RXDPID_SHIFT)
+# define OTGFS_DOEPTSIZ_RXDPID_DATA2 (1 << OTGFS_DOEPTSIZ_RXDPID_SHIFT)
+# define OTGFS_DOEPTSIZ_RXDPID_DATA1 (2 << OTGFS_DOEPTSIZ_RXDPID_SHIFT)
+# define OTGFS_DOEPTSIZ_RXDPID_MDATA (3 << OTGFS_DOEPTSIZ_RXDPID_SHIFT)
+ /* Bit 31: Reserved, must be kept at reset value */
+/* Power and clock gating registers */
+
+/* Power and clock gating control register */
+
+#define OTGFS_PCGCCTL_STPPCLK (1 << 0) /* Bit 0: Stop PHY clock */
+#define OTGFS_PCGCCTL_GATEHCLK (1 << 1) /* Bit 1: Gate HCLK */
+ /* Bits 2-3: Reserved, must be kept at reset value */
+#define OTGFS_PCGCCTL_PHYSUSP (1 << 4) /* Bit 4: PHY Suspended */
+ /* Bits 5-31: Reserved, must be kept at reset value */
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_OTGFS_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_pwr.h b/nuttx/arch/arm/src/stm32/chip/stm32_pwr.h
new file mode 100644
index 000000000..2ece6a357
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_pwr.h
@@ -0,0 +1,103 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_pwr.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_CHIP_STM32_PWR_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_PWR_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_PWR_CR_OFFSET 0x0000 /* Power control register */
+#define STM32_PWR_CSR_OFFSET 0x0004 /* Power control/status register */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_PWR_CR (STM32_PWR_BASE+STM32_PWR_CR_OFFSET)
+#define STM32_PWR_CSR (STM32_PWR_BASE+STM32_PWR_CSR_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* Power control register */
+
+#define PWR_CR_LPDS (1 << 0) /* Bit 0: Low-Power Deepsleep */
+#define PWR_CR_PDDS (1 << 1) /* Bit 1: Power Down Deepsleep */
+#define PWR_CR_CWUF (1 << 2) /* Bit 2: Clear Wakeup Flag */
+#define PWR_CR_CSBF (1 << 3) /* Bit 3: Clear Standby Flag */
+#define PWR_CR_PVDE (1 << 4) /* Bit 4: Power Voltage Detector Enable */
+#define PWR_CR_PLS_SHIFT (5) /* Bits 7-5: PVD Level Selection */
+#define PWR_CR_PLS_MASK (7 << PWR_CR_PLS_SHIFT)
+# define PWR_CR_2p2V (0 << PWR_CR_PLS_SHIFT) /* 000: 2.2V */
+# define PWR_CR_2p3V (1 << PWR_CR_PLS_SHIFT) /* 001: 2.3V */
+# define PWR_CR_2p4V (2 << PWR_CR_PLS_SHIFT) /* 010: 2.4V */
+# define PWR_CR_2p5V (3 << PWR_CR_PLS_SHIFT) /* 011: 2.5V */
+# define PWR_CR_2p6V (4 << PWR_CR_PLS_SHIFT) /* 100: 2.6V */
+# define PWR_CR_2p7V (5 << PWR_CR_PLS_SHIFT) /* 101: 2.7V */
+# define PWR_CR_2p8V (6 << PWR_CR_PLS_SHIFT) /* 110: 2.8V */
+# define PWR_CR_2p9V (7 << PWR_CR_PLS_SHIFT) /* 111: 2.9V */
+#define PWR_CR_DBP (1 << 8) /* Bit 8: Disable Backup Domain write protection */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define PWR_CR_FPDS (1 << 9) /* Bit 9: Flash power down in Stop mode */
+# define PWR_CR_VOS (1 << 14) /* Bit 14: Regulator voltage scaling output selection */
+#endif
+
+/* Power control/status register */
+
+#define PWR_CSR_WUF (1 << 0) /* Bit 0: Wakeup Flag */
+#define PWR_CSR_SBF (1 << 1) /* Bit 1: Standby Flag */
+#define PWR_CSR_PVDO (1 << 2) /* Bit 2: PVD Output */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define PWR_CSR_BRR (1 << 3) /* Bit 3: Backup regulator ready */
+#endif
+
+#define PWR_CSR_EWUP (1 << 8) /* Bit 8: Enable WKUP pin */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define PWR_CSR_BRE (1 << 9) /* Bit 9: Backup regulator enable */
+# define PWR_CSR_VOSRDY (1 << 14) /* Bit 14: Regulator voltage scaling output selection ready bite */
+#endif
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_PWR_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_sdio.h b/nuttx/arch/arm/src/stm32/chip/stm32_sdio.h
new file mode 100644
index 000000000..d2af8a32c
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_sdio.h
@@ -0,0 +1,291 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_sdio.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_CHIP_STM32_SDIO_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_SDIO_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_SDIO_POWER_OFFSET 0x0000 /* SDIO power control register */
+#define STM32_SDIO_CLKCR_OFFSET 0x0004 /* SDI clock control register */
+#define STM32_SDIO_ARG_OFFSET 0x0008 /* SDIO argument register */
+#define STM32_SDIO_CMD_OFFSET 0x000c /* SDIO command register */
+#define STM32_SDIO_RESPCMD_OFFSET 0x0010 /* SDIO command response register */
+#define STM32_SDIO_RESP_OFFSET(n) (0x0010+4*(n))
+#define STM32_SDIO_RESP1_OFFSET 0x0014 /* SDIO response 1 register */
+#define STM32_SDIO_RESP2_OFFSET 0x0018 /* SDIO response 2 register */
+#define STM32_SDIO_RESP3_OFFSET 0x001c /* SDIO response 3 register */
+#define STM32_SDIO_RESP4_OFFSET 0x0020 /* SDIO response 4 register */
+#define STM32_SDIO_DTIMER_OFFSET 0x0024 /* SDIO data timer register */
+#define STM32_SDIO_DLEN_OFFSET 0x0028 /* SDIO data length register */
+#define STM32_SDIO_DCTRL_OFFSET 0x002c /* SDIO data control register */
+#define STM32_SDIO_DCOUNT_OFFSET 0x0030 /* SDIO data counter register */
+#define STM32_SDIO_STA_OFFSET 0x0034 /* SDIO status register */
+#define STM32_SDIO_ICR_OFFSET 0x0038 /* SDIO interrupt clear register */
+#define STM32_SDIO_MASK_OFFSET 0x003c /* SDIO mask register */
+#define STM32_SDIO_FIFOCNT_OFFSET 0x0048 /* SDIO FIFO counter register */
+#define STM32_SDIO_FIFO_OFFSET 0x0080 /* SDIO data FIFO register */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_SDIO_POWER (STM32_SDIO_BASE+STM32_SDIO_POWER_OFFSET)
+#define STM32_SDIO_CLKCR (STM32_SDIO_BASE+STM32_SDIO_CLKCR_OFFSET)
+#define STM32_SDIO_ARG (STM32_SDIO_BASE+STM32_SDIO_ARG_OFFSET)
+#define STM32_SDIO_CMD (STM32_SDIO_BASE+STM32_SDIO_CMD_OFFSET)
+#define STM32_SDIO_RESPCMD (STM32_SDIO_BASE+STM32_SDIO_RESPCMD_OFFSET)
+#define STM32_SDIO_RESP(n) (STM32_SDIO_BASE+STM32_SDIO_RESP_OFFSET(n))
+#define STM32_SDIO_RESP1 (STM32_SDIO_BASE+STM32_SDIO_RESP1_OFFSET)
+#define STM32_SDIO_RESP2 (STM32_SDIO_BASE+STM32_SDIO_RESP2_OFFSET)
+#define STM32_SDIO_RESP3 (STM32_SDIO_BASE+STM32_SDIO_RESP3_OFFSET)
+#define STM32_SDIO_RESP4 (STM32_SDIO_BASE+STM32_SDIO_RESP4_OFFSET)
+#define STM32_SDIO_DTIMER (STM32_SDIO_BASE+STM32_SDIO_DTIMER_OFFSET)
+#define STM32_SDIO_DLEN (STM32_SDIO_BASE+STM32_SDIO_DLEN_OFFSET)
+#define STM32_SDIO_DCTRL (STM32_SDIO_BASE+STM32_SDIO_DCTRL_OFFSET)
+#define STM32_SDIO_DCOUNT (STM32_SDIO_BASE+STM32_SDIO_DCOUNT_OFFSET)
+#define STM32_SDIO_STA (STM32_SDIO_BASE+STM32_SDIO_STA_OFFSET)
+#define STM32_SDIO_ICR (STM32_SDIO_BASE+STM32_SDIO_ICR_OFFSET)
+#define STM32_SDIO_MASK (STM32_SDIO_BASE+STM32_SDIO_MASK_OFFSET)
+#define STM32_SDIO_FIFOCNT (STM32_SDIO_BASE+STM32_SDIO_FIFOCNT_OFFSET)
+#define STM32_SDIO_FIFO (STM32_SDIO_BASE+STM32_SDIO_FIFO_OFFSET)
+
+/* Bit-band (BB) base addresses ****************************************************/
+
+#define STM32_SDIO_OFFSET (STM32_SDIO_BASE-STM32_PERIPH_BASE)
+
+#define STM32_SDIO_POWER_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_POWER_OFFSET)<<5))
+#define STM32_SDIO_CLKCR_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_CLKCR_OFFSET)<<5))
+#define STM32_SDIO_ARG_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_ARG_OFFSET)<<5))
+#define STM32_SDIO_CMD_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_CMD_OFFSET)<<5))
+#define STM32_SDIO_RESPCMD_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESPCMD_OFFSET)<<5))
+#define STM32_SDIO_RESP_BB(n) (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP_OFFSET(n))<<5))
+#define STM32_SDIO_RESP1_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP1_OFFSET)<<5))
+#define STM32_SDIO_RESP2_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP2_OFFSET)<<5))
+#define STM32_SDIO_RESP3_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP3_OFFSET)<<5))
+#define STM32_SDIO_RESP4_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_RESP4_OFFSET)<<5))
+#define STM32_SDIO_DTIMER_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_DTIMER_OFFSET)<<5))
+#define STM32_SDIO_DLEN_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_DLEN_OFFSET)<<5))
+#define STM32_SDIO_DCTRL_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_DCTRL_OFFSET)<<5))
+#define STM32_SDIO_DCOUNT_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_DCOUNT_OFFSET)<<5))
+#define STM32_SDIO_STA_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_STA_OFFSET)<<5))
+#define STM32_SDIO_ICR_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_ICR_OFFSET)<<5))
+#define STM32_SDIO_MASK_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_MASK_OFFSET)<<5))
+#define STM32_SDIO_FIFOCNT_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_FIFOCNT_OFFSET)<<5))
+#define STM32_SDIO_FIFO_BB (STM32_PERIPHBB_BASE+((STM32_SDIO_OFFSET+STM32_SDIO_FIFO_OFFSET)<<5))
+
+/* Register Bitfield Definitions ****************************************************/
+
+#define SDIO_POWER_PWRCTRL_SHIFT (0) /* Bits 0-1: Power supply control bits */
+#define SDIO_POWER_PWRCTRL_MASK (3 << SDIO_POWER_PWRCTRL_SHIFT)
+# define SDIO_POWER_PWRCTRL_OFF (0 << SDIO_POWER_PWRCTRL_SHIFT) /* 00: Power-off: card clock stopped */
+# define SDIO_POWER_PWRCTRL_PWRUP (2 << SDIO_POWER_PWRCTRL_SHIFT) /* 10: Reserved power-up */
+# define SDIO_POWER_PWRCTRL_ON (3 << SDIO_POWER_PWRCTRL_SHIFT) /* 11: Power-on: card is clocked */
+
+#define SDIO_POWER_RESET (0) /* Reset value */
+
+#define SDIO_CLKCR_CLKDIV_SHIFT (0) /* Bits 7-0: Clock divide factor */
+#define SDIO_CLKCR_CLKDIV_MASK (0xff << SDIO_CLKCR_CLKDIV_SHIFT)
+#define SDIO_CLKCR_CLKEN (1 << 8) /* Bit 8: Clock enable bit */
+#define SDIO_CLKCR_PWRSAV (1 << 9) /* Bit 9: Power saving configuration bit */
+#define SDIO_CLKCR_BYPASS (1 << 10) /* Bit 10: Clock divider bypass enable bit */
+#define SDIO_CLKCR_WIDBUS_SHIFT (11) /* Bits 12-11: Wide bus mode enable bits */
+#define SDIO_CLKCR_WIDBUS_MASK (3 << SDIO_CLKCR_WIDBUS_SHIFT)
+# define SDIO_CLKCR_WIDBUS_D1 (0 << SDIO_CLKCR_WIDBUS_SHIFT) /* 00: Default (SDIO_D0) */
+# define SDIO_CLKCR_WIDBUS_D4 (1 << SDIO_CLKCR_WIDBUS_SHIFT) /* 01: 4-wide (SDIO_D[3:0]) */
+# define SDIO_CLKCR_WIDBUS_D8 (2 << SDIO_CLKCR_WIDBUS_SHIFT) /* 10: 8-wide (SDIO_D[7:0]) */
+#define SDIO_CLKCR_NEGEDGE (1 << 13) /* Bit 13: SDIO_CK dephasing selection bit */
+#define SDIO_CLKCR_HWFC_EN (1 << 14) /* Bit 14: HW Flow Control enable */
+
+#define SDIO_CLKCR_RESET (0) /* Reset value */
+#define SDIO_ARG_RESET (0) /* Reset value */
+
+#define SDIO_CLKCR_CLKEN_BB (STM32_SDIO_CLKCR_BB + (8 * 4))
+#define SDIO_CLKCR_PWRSAV_BB (STM32_SDIO_CLKCR_BB + (9 * 4))
+#define SDIO_CLKCR_BYPASS_BB (STM32_SDIO_CLKCR_BB + (10 * 4))
+#define SDIO_CLKCR_NEGEDGE_BB (STM32_SDIO_CLKCR_BB + (13 * 4))
+#define SDIO_CLKCR_HWFC_EN_BB (STM32_SDIO_CLKCR_BB + (14 * 4))
+
+#define SDIO_CMD_CMDINDEX_SHIFT (0)
+#define SDIO_CMD_CMDINDEX_MASK (0x3f << SDIO_CMD_CMDINDEX_SHIFT)
+#define SDIO_CMD_WAITRESP_SHIFT (6) /* Bits 7-6: Wait for response bits */
+#define SDIO_CMD_WAITRESP_MASK (3 << SDIO_CMD_WAITRESP_SHIFT)
+# define SDIO_CMD_NORESPONSE (0 << SDIO_CMD_WAITRESP_SHIFT) /* 00/10: No response */
+# define SDIO_CMD_SHORTRESPONSE (1 << SDIO_CMD_WAITRESP_SHIFT) /* 01: Short response */
+# define SDIO_CMD_LONGRESPONSE (3 << SDIO_CMD_WAITRESP_SHIFT) /* 11: Long response */
+#define SDIO_CMD_WAITINT (1 << 8) /* Bit 8: CPSM waits for interrupt request */
+#define SDIO_CMD_WAITPEND (1 << 9) /* Bit 9: CPSM Waits for ends of data transfer */
+#define SDIO_CMD_CPSMEN (1 << 10) /* Bit 10: Command path state machine enable */
+#define SDIO_CMD_SUSPEND (1 << 11) /* Bit 11: SD I/O suspend command */
+#define SDIO_CMD_ENDCMD (1 << 12) /* Bit 12: Enable CMD completion */
+#define SDIO_CMD_NIEN (1 << 13) /* Bit 13: not Interrupt Enable */
+#define SDIO_CMD_ATACMD (1 << 14) /* Bit 14: CE-ATA command */
+
+#define SDIO_CMD_RESET (0) /* Reset value */
+
+#define SDIO_CMD_WAITINT_BB (STM32_SDIO_CMD_BB + (8 * 4))
+#define SDIO_CMD_WAITPEND_BB (STM32_SDIO_CMD_BB + (9 * 4))
+#define SDIO_CMD_CPSMEN_BB (STM32_SDIO_CMD_BB + (10 * 4))
+#define SDIO_CMD_SUSPEND_BB (STM32_SDIO_CMD_BB + (11 * 4))
+#define SDIO_CMD_ENCMD_BB (STM32_SDIO_CMD_BB + (12 * 4))
+#define SDIO_CMD_NIEN_BB (STM32_SDIO_CMD_BB + (13 * 4))
+#define SDIO_CMD_ATACMD_BB (STM32_SDIO_CMD_BB + (14 * 4))
+
+#define SDIO_RESPCMD_SHIFT (0)
+#define SDIO_RESPCMD_MASK (0x3f << SDIO_RESPCMD_SHIFT)
+
+#define SDIO_DTIMER_RESET (0) /* Reset value */
+
+#define SDIO_DLEN_SHIFT (0)
+#define SDIO_DLEN_MASK (0x01ffffff << SDIO_DLEN_SHIFT)
+
+#define SDIO_DLEN_RESET (0) /* Reset value */
+
+#define SDIO_DCTRL_DTEN (1 << 0) /* Bit 0: Data transfer enabled bit */
+#define SDIO_DCTRL_DTDIR (1 << 1) /* Bit 1: Data transfer direction */
+#define SDIO_DCTRL_DTMODE (1 << 2) /* Bit 2: Data transfer mode */
+#define SDIO_DCTRL_DMAEN (1 << 3) /* Bit 3: DMA enable bit */
+#define SDIO_DCTRL_DBLOCKSIZE_SHIFT (4) /* Bits 7-4: Data block size */
+#define SDIO_DCTRL_DBLOCKSIZE_MASK (15 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_1BYTE (0 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_2BYTES (1 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_4BYTES (2 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_8BYTES (3 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_16BYTES (4 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_32BYTES (5 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_64BYTES (6 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_128BYTES (7 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_256BYTES (8 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_512BYTES (9 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_1KBYTE (10 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_2KBYTES (11 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_4KBYTES (12 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_8KBYTES (13 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDIO_DCTRL_16KBYTES (14 << SDIO_DCTRL_DBLOCKSIZE_SHIFT)
+#define SDIO_DCTRL_RWSTART (1 << 8) /* Bit 8: Read wait start */
+#define SDIO_DCTRL_RWSTOP (1 << 9) /* Bit 9: Read wait stop */
+#define SDIO_DCTRL_RWMOD (1 << 10) /* Bit 10: Read wait mode */
+#define SDIO_DCTRL_SDIOEN (1 << 11) /* Bit 11: SD I/O enable functions */
+
+#define SDIO_DCTRL_RESET (0) /* Reset value */
+
+#define SDIO_DCTRL_DTEN_BB (STM32_SDIO_DCTRL_BB + (0 * 4))
+#define SDIO_DCTRL_DTDIR_BB (STM32_SDIO_DCTRL_BB + (1 * 4))
+#define SDIO_DCTRL_DTMODE_BB (STM32_SDIO_DCTRL_BB + (2 * 4))
+#define SDIO_DCTRL_DMAEN_BB (STM32_SDIO_DCTRL_BB + (3 * 4))
+#define SDIO_DCTRL_RWSTART_BB (STM32_SDIO_DCTRL_BB + (8 * 4))
+#define SDIO_DCTRL_RWSTOP_BB (STM32_SDIO_DCTRL_BB + (9 * 4))
+#define SDIO_DCTRL_RWMOD_BB (STM32_SDIO_DCTRL_BB + (10 * 4))
+#define SDIO_DCTRL_SDIOEN_BB (STM32_SDIO_DCTRL_BB + (11 * 4))
+
+#define SDIO_DATACOUNT_SHIFT (0)
+#define SDIO_DATACOUNT_MASK (0x01ffffff << SDIO_DATACOUNT_SHIFT)
+
+#define SDIO_STA_CCRCFAIL (1 << 0) /* Bit 0: Command response CRC fail */
+#define SDIO_STA_DCRCFAIL (1 << 1) /* Bit 1: Data block CRC fail */
+#define SDIO_STA_CTIMEOUT (1 << 2) /* Bit 2: Command response timeout */
+#define SDIO_STA_DTIMEOUT (1 << 3) /* Bit 3: Data timeout */
+#define SDIO_STA_TXUNDERR (1 << 4) /* Bit 4: Transmit FIFO underrun error */
+#define SDIO_STA_RXOVERR (1 << 5) /* Bit 5: Received FIFO overrun error */
+#define SDIO_STA_CMDREND (1 << 6) /* Bit 6: Command response received */
+#define SDIO_STA_CMDSENT (1 << 7) /* Bit 7: Command sent */
+#define SDIO_STA_DATAEND (1 << 8) /* Bit 8: Data end */
+#define SDIO_STA_STBITERR (1 << 9) /* Bit 9: Start bit not detected */
+#define SDIO_STA_DBCKEND (1 << 10) /* Bit 10: Data block sent/received */
+#define SDIO_STA_CMDACT (1 << 11) /* Bit 11: Command transfer in progress */
+#define SDIO_STA_TXACT (1 << 12) /* Bit 12: Data transmit in progress */
+#define SDIO_STA_RXACT (1 << 13) /* Bit 13: Data receive in progress */
+#define SDIO_STA_TXFIFOHE (1 << 14) /* Bit 14: Transmit FIFO half empty */
+#define SDIO_STA_RXFIFOHF (1 << 15) /* Bit 15: Receive FIFO half full */
+#define SDIO_STA_TXFIFOF (1 << 16) /* Bit 16: Transmit FIFO full */
+#define SDIO_STA_RXFIFOF (1 << 17) /* Bit 17: Receive FIFO full */
+#define SDIO_STA_TXFIFOE (1 << 18) /* Bit 18: Transmit FIFO empty */
+#define SDIO_STA_RXFIFOE (1 << 19) /* Bit 19: Receive FIFO empty */
+#define SDIO_STA_TXDAVL (1 << 20) /* Bit 20: Data available in transmit FIFO */
+#define SDIO_STA_RXDAVL (1 << 21) /* Bit 21: Data available in receive FIFO */
+#define SDIO_STA_SDIOIT (1 << 22) /* Bit 22: SDIO interrupt received */
+#define SDIO_STA_CEATAEND (1 << 23) /* Bit 23: CMD6 CE-ATA command completion */
+
+#define SDIO_ICR_CCRCFAILC (1 << 0) /* Bit 0: CCRCFAIL flag clear bit */
+#define SDIO_ICR_DCRCFAILC (1 << 1) /* Bit 1: DCRCFAIL flag clear bit */
+#define SDIO_ICR_CTIMEOUTC (1 << 2) /* Bit 2: CTIMEOUT flag clear bit */
+#define SDIO_ICR_DTIMEOUTC (1 << 3) /* Bit 3: DTIMEOUT flag clear bit */
+#define SDIO_ICR_TXUNDERRC (1 << 4) /* Bit 4: TXUNDERR flag clear bit */
+#define SDIO_ICR_RXOVERRC (1 << 5) /* Bit 5: RXOVERR flag clear bit */
+#define SDIO_ICR_CMDRENDC (1 << 6) /* Bit 6: CMDREND flag clear bit */
+#define SDIO_ICR_CMDSENTC (1 << 7) /* Bit 7: CMDSENT flag clear bit */
+#define SDIO_ICR_DATAENDC (1 << 8) /* Bit 8: DATAEND flag clear bit */
+#define SDIO_ICR_STBITERRC (1 << 9) /* Bit 9: STBITERR flag clear bit */
+#define SDIO_ICR_DBCKENDC (1 << 10) /* Bit 10: DBCKEND flag clear bit */
+#define SDIO_ICR_SDIOITC (1 << 22) /* Bit 22: SDIOIT flag clear bit */
+#define SDIO_ICR_CEATAENDC (1 << 23) /* Bit 23: CEATAEND flag clear bit */
+
+#define SDIO_ICR_RESET 0x00c007ff
+#define SDIO_ICR_STATICFLAGS 0x000005ff
+
+#define SDIO_MASK_CCRCFAILIE (1 << 0) /* Bit 0: Command CRC fail interrupt enable */
+#define SDIO_MASK_DCRCFAILIE (1 << 1) /* Bit 1: Data CRC fail interrupt enable */
+#define SDIO_MASK_CTIMEOUTIE (1 << 2) /* Bit 2: Command timeout interrupt enable */
+#define SDIO_MASK_DTIMEOUTIE (1 << 3) /* Bit 3: Data timeout interrupt enable */
+#define SDIO_MASK_TXUNDERRIE (1 << 4) /* Bit 4: Tx FIFO underrun error interrupt enable */
+#define SDIO_MASK_RXOVERRIE (1 << 5) /* Bit 5: Rx FIFO overrun error interrupt enable */
+#define SDIO_MASK_CMDRENDIE (1 << 6) /* Bit 6: Command response received interrupt enable */
+#define SDIO_MASK_CMDSENTIE (1 << 7) /* Bit 7: Command sent interrupt enable */
+#define SDIO_MASK_DATAENDIE (1 << 8) /* Bit 8: Data end interrupt enable */
+#define SDIO_MASK_STBITERRIE (1 << 9) /* Bit 9: Start bit error interrupt enable */
+#define SDIO_MASK_DBCKENDIE (1 << 10) /* Bit 10: Data block end interrupt enable */
+#define SDIO_MASK_CMDACTIE (1 << 11) /* Bit 11: Command acting interrupt enable */
+#define SDIO_MASK_TXACTIE (1 << 12) /* Bit 12: Data transmit acting interrupt enable */
+#define SDIO_MASK_RXACTIE (1 << 13) /* Bit 13: Data receive acting interrupt enable */
+#define SDIO_MASK_TXFIFOHEIE (1 << 14) /* Bit 14: Tx FIFO half empty interrupt enable */
+#define SDIO_MASK_RXFIFOHFIE (1 << 15) /* Bit 15: Rx FIFO half full interrupt enable */
+#define SDIO_MASK_TXFIFOFIE (1 << 16) /* Bit 16: Tx FIFO full interrupt enable */
+#define SDIO_MASK_RXFIFOFIE (1 << 17) /* Bit 17: Rx FIFO full interrupt enable */
+#define SDIO_MASK_TXFIFOEIE (1 << 18) /* Bit 18: Tx FIFO empty interrupt enable */
+#define SDIO_MASK_RXFIFOEIE (1 << 19) /* Bit 19: Rx FIFO empty interrupt enable */
+#define SDIO_MASK_TXDAVLIE (1 << 20) /* Bit 20: Data available in Tx FIFO interrupt enable */
+#define SDIO_MASK_RXDAVLIE (1 << 21) /* Bit 21: Data available in Rx FIFO interrupt enable */
+#define SDIO_MASK_SDIOITIE (1 << 22) /* Bit 22: SDIO mode interrupt received interrupt enable */
+#define SDIO_MASK_CEATAENDIE (1 << 23) /* Bit 23: CE-ATA command completion interrupt enable */
+
+#define SDIO_MASK_RESET (0)
+
+#define SDIO_FIFOCNT_SHIFT (0)
+#define SDIO_FIFOCNT_MASK (0x01ffffff << SDIO_FIFOCNT_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_SDIO_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_spi.h b/nuttx/arch/arm/src/stm32/chip/stm32_spi.h
new file mode 100644
index 000000000..d80c447bb
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_spi.h
@@ -0,0 +1,205 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_spi.h
+ *
+ * Copyright (C) 2009, 2011 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_STC_STM32_CHIP_STM32_SPI_H
+#define __ARCH_ARM_STC_STM32_CHIP_STM32_SPI_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#define STM32_SPI_CLK_MAX 18000000UL /* Maximum allowed speed as per specifications for all SPIs */
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_SPI_CR1_OFFSET 0x0000 /* SPI Control Register 1 (16-bit) */
+#define STM32_SPI_CR2_OFFSET 0x0004 /* SPI control register 2 (16-bit) */
+#define STM32_SPI_SR_OFFSET 0x0008 /* SPI status register (16-bit) */
+#define STM32_SPI_DR_OFFSET 0x000c /* SPI data register (16-bit) */
+#define STM32_SPI_CRCPR_OFFSET 0x0010 /* SPI CRC polynomial register (16-bit) */
+#define STM32_SPI_RXCRCR_OFFSET 0x0014 /* SPI Rx CRC register (16-bit) */
+#define STM32_SPI_TXCRCR_OFFSET 0x0018 /* SPI Tx CRC register (16-bit) */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_SPI_I2SCFGR_OFFSET 0x001c /* I2S configuration register */
+# define STM32_SPI_I2SPR_OFFSET 0x0020 /* I2S prescaler register */
+#endif
+
+/* Register Addresses ***************************************************************/
+
+#if STM32_NSPI > 0
+# define STM32_SPI1_CR1 (STM32_SPI1_BASE+STM32_SPI_CR1_OFFSET)
+# define STM32_SPI1_CR2 (STM32_SPI1_BASE+STM32_SPI_CR2_OFFSET)
+# define STM32_SPI1_SR (STM32_SPI1_BASE+STM32_SPI_SR_OFFSET)
+# define STM32_SPI1_DR (STM32_SPI1_BASE+STM32_SPI_DR_OFFSET)
+# define STM32_SPI1_CRCPR (STM32_SPI1_BASE+STM32_SPI_CRCPR_OFFSET)
+# define STM32_SPI1_RXCRCR (STM32_SPI1_BASE+STM32_SPI_RXCRCR_OFFSET)
+# define STM32_SPI1_TXCRCR (STM32_SPI1_BASE+STM32_SPI_TXCRCR_OFFSET)
+#endif
+
+#if STM32_NSPI > 1
+# define STM32_SPI2_CR1 (STM32_SPI2_BASE+STM32_SPI_CR1_OFFSET)
+# define STM32_SPI2_CR2 (STM32_SPI2_BASE+STM32_SPI_CR2_OFFSET)
+# define STM32_SPI2_SR (STM32_SPI2_BASE+STM32_SPI_SR_OFFSET)
+# define STM32_SPI2_DR (STM32_SPI2_BASE+STM32_SPI_DR_OFFSET)
+# define STM32_SPI2_CRCPR (STM32_SPI2_BASE+STM32_SPI_CRCPR_OFFSET)
+# define STM32_SPI2_RXCRCR (STM32_SPI2_BASE+STM32_SPI_RXCRCR_OFFSET)
+# define STM32_SPI2_TXCRCR (STM32_SPI2_BASE+STM32_SPI_TXCRCR_OFFSET)
+# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_SPI2_I2SCFGR (STM32_SPI2_BASE+STM32_SPI_I2SCFGR_OFFSET)
+# define STM32_SPI2_I2SPR (STM32_SPI2_BASE+STM32_SPI_I2SPR_OFFSET)
+# endif
+#endif
+
+#if STM32_NSPI > 2
+# define STM32_SPI3_CR1 (STM32_SPI3_BASE+STM32_SPI_CR1_OFFSET)
+# define STM32_SPI3_CR2 (STM32_SPI3_BASE+STM32_SPI_CR2_OFFSET)
+# define STM32_SPI3_SR (STM32_SPI3_BASE+STM32_SPI_SR_OFFSET)
+# define STM32_SPI3_DR (STM32_SPI3_BASE+STM32_SPI_DR_OFFSET)
+# define STM32_SPI3_CRCPR (STM32_SPI3_BASE+STM32_SPI_CRCPR_OFFSET)
+# define STM32_SPI3_RXCRCR (STM32_SPI3_BASE+STM32_SPI_RXCRCR_OFFSET)
+# define STM32_SPI3_TXCRCR (STM32_SPI3_BASE+STM32_SPI_TXCRCR_OFFSET)
+# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_SPI3_I2SCFGR (STM32_SPI3_BASE+STM32_SPI_I2SCFGR_OFFSET)
+# define STM32_SPI3_I2SPR (STM32_SPI3_BASE+STM32_SPI_I2SPR_OFFSET)
+# endif
+#endif
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* SPI Control Register 1 */
+
+#define SPI_CR1_CPHA (1 << 0) /* Bit 0: Clock Phase */
+#define SPI_CR1_CPOL (1 << 1) /* Bit 1: Clock Polarity */
+#define SPI_CR1_MSTR (1 << 2) /* Bit 2: Master Selection */
+#define SPI_CR1_BR_SHIFT (3) /* Bits 5:3 Baud Rate Control */
+#define SPI_CR1_BR_MASK (7 << SPI_CR1_BR_SHIFT)
+# define SPI_CR1_FPCLCKd2 (0 << SPI_CR1_BR_SHIFT) /* 000: fPCLK/2 */
+# define SPI_CR1_FPCLCKd4 (1 << SPI_CR1_BR_SHIFT) /* 001: fPCLK/4 */
+# define SPI_CR1_FPCLCKd8 (2 << SPI_CR1_BR_SHIFT) /* 010: fPCLK/8 */
+# define SPI_CR1_FPCLCKd16 (3 << SPI_CR1_BR_SHIFT) /* 011: fPCLK/16 */
+# define SPI_CR1_FPCLCKd32 (4 << SPI_CR1_BR_SHIFT) /* 100: fPCLK/32 */
+# define SPI_CR1_FPCLCKd64 (5 << SPI_CR1_BR_SHIFT) /* 101: fPCLK/64 */
+# define SPI_CR1_FPCLCKd128 (6 << SPI_CR1_BR_SHIFT) /* 110: fPCLK/128 */
+# define SPI_CR1_FPCLCKd256 (7 << SPI_CR1_BR_SHIFT) /* 111: fPCLK/256 */
+#define SPI_CR1_SPE (1 << 6) /* Bit 6: SPI Enable */
+#define SPI_CR1_LSBFIRST (1 << 7) /* Bit 7: Frame Format */
+#define SPI_CR1_SSI (1 << 8) /* Bit 8: Internal slave select */
+#define SPI_CR1_SSM (1 << 9) /* Bit 9: Software slave management */
+#define SPI_CR1_RXONLY (1 << 10) /* Bit 10: Receive only */
+#define SPI_CR1_DFF (1 << 11) /* Bit 11: Data Frame Format */
+#define SPI_CR1_CRCNEXT (1 << 12) /* Bit 12: Transmit CRC next */
+#define SPI_CR1_CRCEN (1 << 13) /* Bit 13: Hardware CRC calculation enable */
+#define SPI_CR1_BIDIOE (1 << 14) /* Bit 14: Output enable in bidirectional mode */
+#define SPI_CR1_BIDIMODE (1 << 15) /* Bit 15: Bidirectional data mode enable */
+
+/* SPI Control Register 2 */
+
+#define SPI_CR2_RXDMAEN (1 << 0) /* Bit 0: Rx Buffer DMA Enable */
+#define SPI_CR2_TXDMAEN (1 << 1) /* Bit 1: Tx Buffer DMA Enable */
+#define SPI_CR2_SSOE (1 << 2) /* Bit 2: SS Output Enable */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_SPI3_FRF (1 << 4) /* Bit 4: Frame format */
+#endif
+
+#define SPI_CR2_ERRIE (1 << 5) /* Bit 5: Error interrupt enable */
+#define SPI_CR2_RXNEIE (1 << 6) /* Bit 6: RX buffer not empty interrupt enable */
+#define SPI_CR2_TXEIE (1 << 7) /* Bit 7: Tx buffer empty interrupt enable */
+
+/* SPI status register */
+
+#define SPI_SR_RXNE (1 << 0) /* Bit 0: Receive buffer not empty */
+#define SPI_SR_TXE (1 << 1) /* Bit 1: Transmit buffer empty */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define SPI_SR_CHSIDE (1 << 2) /* Bit 2: Channel side */
+# define SPI_SR_UDR (1 << 3) /* Bit 3: Underrun flag */
+#endif
+
+#define SPI_SR_CRCERR (1 << 4) /* Bit 4: CRC error flag */
+#define SPI_SR_MODF (1 << 5) /* Bit 5: Mode fault */
+#define SPI_SR_OVR (1 << 6) /* Bit 6: Overrun flag */
+#define SPI_SR_BSY (1 << 7) /* Bit 7: Busy flag */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define SPI_SR_TIFRFE (1 << 8) /* Bit 8: TI frame format error */
+#endif
+
+/* I2S configuration register */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define SPI_I2SCFGR_CHLEN (1 << 0) /* Bit 0: Channel length (number of bits per audio channel) */
+# define SPI_I2SCFGR_DATLEN_SHIFT (1) /* Bit 1-2: Data length to be transferred */
+# define SPI_I2SCFGR_DATLEN_MASK (3 << SPI_I2SCFGR_DATLEN_SHIFT)
+# define SPI_I2SCFGR_DATLEN_16BIT (0 << SPI_I2SCFGR_DATLEN_SHIFT) /* 00: 16-bit data length */
+# define SPI_I2SCFGR_DATLEN_8BIT (1 << SPI_I2SCFGR_DATLEN_SHIFT) /* 01: 24-bit data length */
+# define SPI_I2SCFGR_DATLEN_32BIT (2 << SPI_I2SCFGR_DATLEN_SHIFT) /* 10: 32-bit data length */
+# define SPI_I2SCFGR_CKPOL (1 << 3) /* Bit 3: Steady state clock polarity */
+# define SPI_I2SCFGR_I2SSTD_SHIFT (4) /* Bit 4-5: I2S standard selection */
+# define SPI_I2SCFGR_I2SSTD_MASK (3 << SPI_I2SCFGR_I2SSTD_SHIFT)
+# define SPI_I2SCFGR_I2SSTD_PHILLIPS (xx << SPI_I2SCFGR_I2SSTD_SHIFT) /* 00: I2S Phillips standard. */
+# define SPI_I2SCFGR_I2SSTD_MSB (0 << SPI_I2SCFGR_I2SSTD_SHIFT) /* 01: MSB justified standard (left justified) */
+# define SPI_I2SCFGR_I2SSTD_LSB (2 << SPI_I2SCFGR_I2SSTD_SHIFT) /* 10: LSB justified standard (right justified) */
+# define SPI_I2SCFGR_I2SSTD_PCM (3 << SPI_I2SCFGR_I2SSTD_SHIFT) /* 11: PCM standard */
+# define SPI_I2SCFGR_PCMSYNC (1 << 7) /* Bit 7: PCM frame synchronization */
+# define SPI_I2SCFGR_I2SCFG_SHIFT (8) /* Bit 8-9: I2S configuration mode */
+# define SPI_I2SCFGR_I2SCFG_MASK (3 << SPI_I2SCFGR_I2SCFG_SHIFT)
+# define SPI_I2SCFGR_I2SCFG_STX (0 << SPI_I2SCFGR_I2SCFG_SHIFT) /* 00: Slave - transmit */
+# define SPI_I2SCFGR_I2SCFG_SRX (1 << SPI_I2SCFGR_I2SCFG_SHIFT) /* 01: Slave - receive */
+# define SPI_I2SCFGR_I2SCFG_MTX (2 << SPI_I2SCFGR_I2SCFG_SHIFT) /* 10: Master - transmit */
+# define SPI_I2SCFGR_I2SCFG_MRX (3 << SPI_I2SCFGR_I2SCFG_SHIFT) /* 11: Master - receive */
+# define SPI_I2SCFGR_I2SE (1 << 10) /* Bit 10: I2S Enable */
+# define SPI_I2SCFGR_I2SMOD (1 << 11) /* Bit 11: I2S mode selection */
+#endif
+
+/* I2S prescaler register */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define SPI_I2SPR_I2SDIV_SHIFT (0) /* Bit 0-7: I2S Linear prescaler */
+# define SPI_I2SPR_I2SDIV_MASK (0xff << SPI_I2SPR_I2SDIV_SHIFT)
+# define SPI_I2SPR_ODD (1 << 8) /* Bit 8: Odd factor for the prescaler */
+# define SPI_I2SPR_MCKOE (1 << 9) /* Bit 9: Master clock output enable */
+#endif
+
+#endif /* __ARCH_ARM_STC_STM32_CHIP_STM32_SPI_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_syscfg.h b/nuttx/arch/arm/src/stm32/chip/stm32_syscfg.h
new file mode 100644
index 000000000..6642b1305
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_syscfg.h
@@ -0,0 +1,151 @@
+/****************************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_syscfg.h
+ *
+ * Copyright (C) 2011 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_STM32_CHIP_STM32_SYSCFG_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_SYSCFG_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+
+/****************************************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************************************/
+
+/* Register Offsets *********************************************************************************/
+
+#define STM32_SYSCFG_MEMRMP_OFFSET 0x0000 /* SYSCFG memory remap register */
+#define STM32_SYSCFG_PMC_OFFSET 0x0004 /* SYSCFG peripheral mode configuration register */
+
+#define STM32_SYSCFG_EXTICR_OFFSET(p) (0x0008 + ((p) & 0x000c)) /* Registers are displaced by 4! */
+#define STM32_SYSCFG_EXTICR1_OFFSET 0x0008 /* SYSCFG external interrupt configuration register 1 */
+#define STM32_SYSCFG_EXTICR2_OFFSET 0x000c /* SYSCFG external interrupt configuration register 2 */
+#define STM32_SYSCFG_EXTICR3_OFFSET 0x0010 /* SYSCFG external interrupt configuration register 3 */
+#define STM32_SYSCFG_EXTICR4_OFFSET 0x0014 /* SYSCFG external interrupt configuration register 4 */
+
+#define STM32_SYSCFG_CMPCR_OFFSET 0x0020 /* Compensation cell control register */
+
+/* Register Addresses *******************************************************************************/
+
+#define STM32_SYSCFG_MEMRMP (STM32_SYSCFG_BASE+STM32_SYSCFG_MEMRMP_OFFSET)
+#define STM32_SYSCFG_PMC (STM32_SYSCFG_BASE+STM32_SYSCFG_PMC_OFFSET)
+
+#define STM32_SYSCFG_EXTICR(p) (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR_OFFSET(p))
+#define STM32_SYSCFG_EXTICR1 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR1_OFFSET)
+#define STM32_SYSCFG_EXTICR2 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR2_OFFSET)
+#define STM32_SYSCFG_EXTICR3 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR3_OFFSET)
+#define STM32_SYSCFG_EXTICR4 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR4_OFFSET)
+
+#define STM32_SYSCFG_CMPCR (STM32_SYSCFG_BASE+STM32_SYSCFG_CMPCR_OFFSET)
+
+/* Register Bitfield Definitions ********************************************************************/
+
+/* SYSCFG memory remap register */
+
+#define SYSCFG_MEMRMP_SHIFT (0) /* Bits 1:0 MEM_MODE: Memory mapping selection */
+#define SYSCFG_MEMRMP_MASK (3 << SYSCFG_MEMRMP_SHIFT)
+# define SYSCFG_MEMRMP_FLASH (0 << SYSCFG_MEMRMP_SHIFT) /* 00: Main Flash memory mapped at 0x0000 0000 */
+# define SYSCFG_MEMRMP_SYSTEM (1 << SYSCFG_MEMRMP_SHIFT) /* 01: System Flash memory mapped at 0x0000 0000 */
+# define SYSCFG_MEMRMP_FSMC (2 << SYSCFG_MEMRMP_SHIFT) /* 10: FSMC Bank1 (NOR/PSRAM 1 and 2) mapped at 0x0000 0000 */
+# define SYSCFG_MEMRMP_SRAM (3 << SYSCFG_MEMRMP_SHIFT) /* 11: Embedded SRAM (112kB) mapped at 0x0000 0000 */
+
+/* SYSCFG peripheral mode configuration register */
+
+#define SYSCFG_PMC_MII_RMII_SEL (1 << 23) /* Bit 23: Ethernet PHY interface selection */
+
+/* SYSCFG external interrupt configuration register 1-4 */
+
+#define SYSCFG_EXTICR_PORTA (0) /* 0000: PA[x] pin */
+#define SYSCFG_EXTICR_PORTB (1) /* 0001: PB[x] pin */
+#define SYSCFG_EXTICR_PORTC (2) /* 0010: PC[x] pin */
+#define SYSCFG_EXTICR_PORTD (3) /* 0011: PD[x] pin */
+#define SYSCFG_EXTICR_PORTE (4) /* 0100: PE[x] pin */
+#define SYSCFG_EXTICR_PORTF (5) /* 0101: PF[C] pin */
+#define SYSCFG_EXTICR_PORTG (6) /* 0110: PG[x] pin */
+#define SYSCFG_EXTICR_PORTH (7) /* 0111: PH[x] pin */
+#define SYSCFG_EXTICR_PORTI (8) /* 1000: PI[x] pin */
+
+#define SYSCFG_EXTICR_PORT_MASK (15)
+#define SYSCFG_EXTICR_EXTI_SHIFT(g) (((g) & 3) << 2)
+#define SYSCFG_EXTICR_EXTI_MASK(g) (SYSCFG_EXTICR_PORT_MASK << (SYSCFG_EXTICR_EXTI_SHIFT(g)))
+
+#define SYSCFG_EXTICR1_EXTI0_SHIFT (0) /* Bits 0-3: EXTI 0 coinfiguration */
+#define SYSCFG_EXTICR1_EXTI0_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI0_SHIFT)
+#define SYSCFG_EXTICR1_EXTI1_SHIFT (4) /* Bits 4-7: EXTI 1 coinfiguration */
+#define SYSCFG_EXTICR1_EXTI1_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI1_SHIFT)
+#define SYSCFG_EXTICR1_EXTI2_SHIFT (8) /* Bits 8-11: EXTI 2 coinfiguration */
+#define SYSCFG_EXTICR1_EXTI2_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI2_SHIFT)
+#define SYSCFG_EXTICR1_EXTI3_SHIFT (12) /* Bits 12-15: EXTI 3 coinfiguration */
+#define SYSCFG_EXTICR1_EXTI3_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI3_SHIFT)
+
+#define SYSCFG_EXTICR2_EXTI4_SHIFT (0) /* Bits 0-3: EXTI 4 coinfiguration */
+#define SYSCFG_EXTICR2_EXTI4_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI4_SHIFT)
+#define SYSCFG_EXTICR2_EXTI5_SHIFT (4) /* Bits 4-7: EXTI 5 coinfiguration */
+#define SYSCFG_EXTICR2_EXTI5_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI5_SHIFT)
+#define SYSCFG_EXTICR2_EXTI6_SHIFT (8) /* Bits 8-11: EXTI 6 coinfiguration */
+#define SYSCFG_EXTICR2_EXTI6_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI6_SHIFT)
+#define SYSCFG_EXTICR2_EXTI7_SHIFT (12) /* Bits 12-15: EXTI 7 coinfiguration */
+#define SYSCFG_EXTICR2_EXTI7_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI7_SHIFT)
+
+#define SYSCFG_EXTICR3_EXTI8_SHIFT (0) /* Bits 0-3: EXTI 8 coinfiguration */
+#define SYSCFG_EXTICR3_EXTI8_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI8_SHIFT)
+#define SYSCFG_EXTICR3_EXTI9_SHIFT (4) /* Bits 4-7: EXTI 9 coinfiguration */
+#define SYSCFG_EXTICR3_EXTI9_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI9_SHIFT)
+#define SYSCFG_EXTICR3_EXTI10_SHIFT (8) /* Bits 8-11: EXTI 10 coinfiguration */
+#define SYSCFG_EXTICR3_EXTI10_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI10_SHIFT)
+#define SYSCFG_EXTICR3_EXTI11_SHIFT (12) /* Bits 12-15: EXTI 11 coinfiguration */
+#define SYSCFG_EXTICR3_EXTI11_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI11_SHIFT)
+
+#define SYSCFG_EXTICR4_EXTI12_SHIFT (0) /* Bits 0-3: EXTI 12 coinfiguration */
+#define SYSCFG_EXTICR4_EXTI12_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI12_SHIFT)
+#define SYSCFG_EXTICR4_EXTI13_SHIFT (4) /* Bits 4-7: EXTI 13 coinfiguration */
+#define SYSCFG_EXTICR4_EXTI13_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI13_SHIFT)
+#define SYSCFG_EXTICR4_EXTI14_SHIFT (8) /* Bits 8-11: EXTI 14 coinfiguration */
+#define SYSCFG_EXTICR4_EXTI14_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI14_SHIFT)
+#define SYSCFG_EXTICR4_EXTI15_SHIFT (12) /* Bits 12-15: EXTI 15 coinfiguration */
+#define SYSCFG_EXTICR4_EXTI15_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI15_SHIFT)
+
+/* Compensation cell control register */
+
+#define SYSCFG_CMPCR_CMPPD (1 << 0) /* Bit 0: Compensation cell power-down */
+#define SYSCFG_CMPCR_READY (1 << 8) /* Bit 8: Compensation cell ready flag */
+
+#endif /* CONFIG_STM32_STM32F20XX || CONFIG_STM32_STM32F40XX */
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_SYSCFG_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_tim.h b/nuttx/arch/arm/src/stm32/chip/stm32_tim.h
new file mode 100644
index 000000000..3713f8b79
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_tim.h
@@ -0,0 +1,1029 @@
+/****************************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_tim.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_CHIP_STM32_TIM_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_TIM_H
+
+/****************************************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************************************/
+
+/* Register Offsets *********************************************************************************/
+
+/* Basic Timers - TIM6 and TIM7 */
+
+#define STM32_BTIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */
+#define STM32_BTIM_CR2_OFFSET 0x0004 /* Control register 2 (16-bit) */
+#define STM32_BTIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */
+#define STM32_BTIM_SR_OFFSET 0x0010 /* Status register (16-bit) */
+#define STM32_BTIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */
+#define STM32_BTIM_CNT_OFFSET 0x0024 /* Counter (16-bit) */
+#define STM32_BTIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */
+#define STM32_BTIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */
+
+/* 16-/32-bit General Timers with DMA: TIM2, TM3, TIM4, and TIM5
+ * 16-bit General Timers without DMA: TIM9, TIM10, TIM11, TIM12, TIM13, and TIM14
+ * For the STM32F10xx all timers are 16-bit.
+ * For the STM32F20xx and STM32F40xx, TIM2 and 5 are 32-bit
+ */
+
+#define STM32_GTIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */
+#define STM32_GTIM_CR2_OFFSET 0x0004 /* Control register 2 (16-bit, TIM2-5 only) */
+#define STM32_GTIM_SMCR_OFFSET 0x0008 /* Slave mode control register (16-bit, TIM2-5 only) */
+#define STM32_GTIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */
+#define STM32_GTIM_SR_OFFSET 0x0010 /* Status register (16-bit) */
+#define STM32_GTIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */
+#define STM32_GTIM_CCMR1_OFFSET 0x0018 /* Capture/compare mode register 1 (16-bit) */
+#define STM32_GTIM_CCMR2_OFFSET 0x001c /* Capture/compare mode register 2 (16-bit, TIM2-5 only) */
+#define STM32_GTIM_CCER_OFFSET 0x0020 /* Capture/compare enable register (16-bit) */
+#define STM32_GTIM_CNT_OFFSET 0x0024 /* Counter (16-bit or 32-bit STM3240 TIM2 and 5 only) */
+#define STM32_GTIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */
+#define STM32_GTIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */
+#define STM32_GTIM_CCR1_OFFSET 0x0034 /* Capture/compare register 1 (16-bit or 32-bit STM3240 TIM2/5 only) */
+#define STM32_GTIM_CCR2_OFFSET 0x0038 /* Capture/compare register 2 (16-bit TIM2-5 only or 32-bit STM3240 TIM2/5 only) */
+#define STM32_GTIM_CCR3_OFFSET 0x003c /* Capture/compare register 3 (16-bit TIM2-5 only or 32-bit STM3240 TIM2/5 only) */
+#define STM32_GTIM_CCR4_OFFSET 0x0040 /* Capture/compare register 4 (16-bit TIM2-5 only or 32-bit STM3240 TIM2/5 only) */
+#define STM32_GTIM_DCR_OFFSET 0x0048 /* DMA control register (16-bit, TIM2-5 only) */
+#define STM32_GTIM_DMAR_OFFSET 0x004c /* DMA address for burst mode (16-bit, TIM2-5 only) */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_GTIM_OR_OFFSET 0x0050 /* Timer 2/5/11 option register */
+#endif
+
+/* Advanced Timers - TIM1 and TIM8 */
+
+#define STM32_ATIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */
+#define STM32_ATIM_CR2_OFFSET 0x0004 /* Control register 2 *(16-bit) */
+#define STM32_ATIM_SMCR_OFFSET 0x0008 /* Slave mode control register (16-bit) */
+#define STM32_ATIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */
+#define STM32_ATIM_SR_OFFSET 0x0010 /* Status register (16-bit) */
+#define STM32_ATIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */
+#define STM32_ATIM_CCMR1_OFFSET 0x0018 /* Capture/compare mode register 1 (16-bit) */
+#define STM32_ATIM_CCMR2_OFFSET 0x001c /* Capture/compare mode register 2 (16-bit) */
+#define STM32_ATIM_CCER_OFFSET 0x0020 /* Capture/compare enable register (16-bit) */
+#define STM32_ATIM_CNT_OFFSET 0x0024 /* Counter (16-bit) */
+#define STM32_ATIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */
+#define STM32_ATIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */
+#define STM32_ATIM_RCR_OFFSET 0x0030 /* Repetition counter register (16-bit) */
+#define STM32_ATIM_CCR1_OFFSET 0x0034 /* Capture/compare register 1 (16-bit) */
+#define STM32_ATIM_CCR2_OFFSET 0x0038 /* Capture/compare register 2 (16-bit) */
+#define STM32_ATIM_CCR3_OFFSET 0x003c /* Capture/compare register 3 (16-bit) */
+#define STM32_ATIM_CCR4_OFFSET 0x0040 /* Capture/compare register 4 (16-bit) */
+#define STM32_ATIM_BDTR_OFFSET 0x0044 /* Break and dead-time register (16-bit) */
+#define STM32_ATIM_DCR_OFFSET 0x0048 /* DMA control register (16-bit) */
+#define STM32_ATIM_DMAR_OFFSET 0x004c /* DMA address for burst mode (16-bit) */
+
+/* Register Addresses *******************************************************************************/
+
+/* Advanced Timers - TIM1 and TIM8 */
+
+#if STM32_NATIM > 0
+# define STM32_TIM1_CR1 (STM32_TIM1_BASE+STM32_ATIM_CR1_OFFSET)
+# define STM32_TIM1_CR2 (STM32_TIM1_BASE+STM32_ATIM_CR2_OFFSET)
+# define STM32_TIM1_SMCR (STM32_TIM1_BASE+STM32_ATIM_SMCR_OFFSET)
+# define STM32_TIM1_DIER (STM32_TIM1_BASE+STM32_ATIM_DIER_OFFSET)
+# define STM32_TIM1_SR (STM32_TIM1_BASE+STM32_ATIM_SR_OFFSET)
+# define STM32_TIM1_EGR (STM32_TIM1_BASE+STM32_ATIM_EGR_OFFSET)
+# define STM32_TIM1_CCMR1 (STM32_TIM1_BASE+STM32_ATIM_CCMR1_OFFSET)
+# define STM32_TIM1_CCMR2 (STM32_TIM1_BASE+STM32_ATIM_CCMR2_OFFSET)
+# define STM32_TIM1_CCER (STM32_TIM1_BASE+STM32_ATIM_CCER_OFFSET)
+# define STM32_TIM1_CNT (STM32_TIM1_BASE+STM32_ATIM_CNT_OFFSET)
+# define STM32_TIM1_PSC (STM32_TIM1_BASE+STM32_ATIM_PSC_OFFSET)
+# define STM32_TIM1_ARR (STM32_TIM1_BASE+STM32_ATIM_ARR_OFFSET)
+# define STM32_TIM1_RCR (STM32_TIM1_BASE+STM32_ATIM_RCR_OFFSET)
+# define STM32_TIM1_CCR1 (STM32_TIM1_BASE+STM32_ATIM_CCR1_OFFSET)
+# define STM32_TIM1_CCR2 (STM32_TIM1_BASE+STM32_ATIM_CCR2_OFFSET)
+# define STM32_TIM1_CCR3 (STM32_TIM1_BASE+STM32_ATIM_CCR3_OFFSET)
+# define STM32_TIM1_CCR4 (STM32_TIM1_BASE+STM32_ATIM_CCR4_OFFSET)
+# define STM32_TIM1_BDTR (STM32_TIM1_BASE+STM32_ATIM_BDTR_OFFSET)
+# define STM32_TIM1_DCR (STM32_TIM1_BASE+STM32_ATIM_DCR_OFFSET)
+# define STM32_TIM1_DMAR (STM32_TIM1_BASE+STM32_ATIM_DMAR_OFFSET)
+#endif
+
+#if STM32_NATIM > 1
+# define STM32_TIM8_CR1 (STM32_TIM8_BASE+STM32_ATIM_CR1_OFFSET)
+# define STM32_TIM8_CR2 (STM32_TIM8_BASE+STM32_ATIM_CR2_OFFSET)
+# define STM32_TIM8_SMCR (STM32_TIM8_BASE+STM32_ATIM_SMCR_OFFSET)
+# define STM32_TIM8_DIER (STM32_TIM8_BASE+STM32_ATIM_DIER_OFFSET)
+# define STM32_TIM8_SR (STM32_TIM8_BASE+STM32_ATIM_SR_OFFSET)
+# define STM32_TIM8_EGR (STM32_TIM8_BASE+STM32_ATIM_EGR_OFFSET)
+# define STM32_TIM8_CCMR1 (STM32_TIM8_BASE+STM32_ATIM_CCMR1_OFFSET)
+# define STM32_TIM8_CCMR2 (STM32_TIM8_BASE+STM32_ATIM_CCMR2_OFFSET)
+# define STM32_TIM8_CCER (STM32_TIM8_BASE+STM32_ATIM_CCER_OFFSET)
+# define STM32_TIM8_CNT (STM32_TIM8_BASE+STM32_ATIM_CNT_OFFSET)
+# define STM32_TIM8_PSC (STM32_TIM8_BASE+STM32_ATIM_PSC_OFFSET)
+# define STM32_TIM8_ARR (STM32_TIM8_BASE+STM32_ATIM_ARR_OFFSET)
+# define STM32_TIM8_RCR (STM32_TIM8_BASE+STM32_ATIM_RCR_OFFSET)
+# define STM32_TIM8_CCR1 (STM32_TIM8_BASE+STM32_ATIM_CCR1_OFFSET)
+# define STM32_TIM8_CCR2 (STM32_TIM8_BASE+STM32_ATIM_CCR2_OFFSET)
+# define STM32_TIM8_CCR3 (STM32_TIM8_BASE+STM32_ATIM_CCR3_OFFSET)
+# define STM32_TIM8_CCR4 (STM32_TIM8_BASE+STM32_ATIM_CCR4_OFFSET)
+# define STM32_TIM8_BDTR (STM32_TIM8_BASE+STM32_ATIM_BDTR_OFFSET)
+# define STM32_TIM8_DCR (STM32_TIM8_BASE+STM32_ATIM_DCR_OFFSET)
+# define STM32_TIM8_DMAR (STM32_TIM8_BASE+STM32_ATIM_DMAR_OFFSET)
+#endif
+
+/* 16-/32-bit General Timers - TIM2, TIM3, TIM4, and TIM5 with DMA.
+ * For the STM32F10xx all timers are 16-bit.
+ * For the STM32F2xx and STM32F40xx, TIM2 and 5 are 32-bit
+ */
+
+#if STM32_NGTIM > 0
+# define STM32_TIM2_CR1 (STM32_TIM2_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM2_CR2 (STM32_TIM2_BASE+STM32_GTIM_CR2_OFFSET)
+# define STM32_TIM2_SMCR (STM32_TIM2_BASE+STM32_GTIM_SMCR_OFFSET)
+# define STM32_TIM2_DIER (STM32_TIM2_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM2_SR (STM32_TIM2_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM2_EGR (STM32_TIM2_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM2_CCMR1 (STM32_TIM2_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM2_CCMR2 (STM32_TIM2_BASE+STM32_GTIM_CCMR2_OFFSET)
+# define STM32_TIM2_CCER (STM32_TIM2_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM2_CNT (STM32_TIM2_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM2_PSC (STM32_TIM2_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM2_ARR (STM32_TIM2_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM2_CCR1 (STM32_TIM2_BASE+STM32_GTIM_CCR1_OFFSET)
+# define STM32_TIM2_CCR2 (STM32_TIM2_BASE+STM32_GTIM_CCR2_OFFSET)
+# define STM32_TIM2_CCR3 (STM32_TIM2_BASE+STM32_GTIM_CCR3_OFFSET)
+# define STM32_TIM2_CCR4 (STM32_TIM2_BASE+STM32_GTIM_CCR4_OFFSET)
+# define STM32_TIM2_DCR (STM32_TIM2_BASE+STM32_GTIM_DCR_OFFSET)
+# define STM32_TIM2_DMAR (STM32_TIM2_BASE+STM32_GTIM_DMAR_OFFSET)
+# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_TIM2_OR (STM32_TIM2_BASE+STM32_GTIM_OR_OFFSET)
+# endif
+#endif
+
+#if STM32_NGTIM > 1
+# define STM32_TIM3_CR1 (STM32_TIM3_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM3_CR2 (STM32_TIM3_BASE+STM32_GTIM_CR2_OFFSET)
+# define STM32_TIM3_SMCR (STM32_TIM3_BASE+STM32_GTIM_SMCR_OFFSET)
+# define STM32_TIM3_DIER (STM32_TIM3_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM3_SR (STM32_TIM3_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM3_EGR (STM32_TIM3_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM3_CCMR1 (STM32_TIM3_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM3_CCMR2 (STM32_TIM3_BASE+STM32_GTIM_CCMR2_OFFSET)
+# define STM32_TIM3_CCER (STM32_TIM3_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM3_CNT (STM32_TIM3_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM3_PSC (STM32_TIM3_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM3_ARR (STM32_TIM3_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM3_CCR1 (STM32_TIM3_BASE+STM32_GTIM_CCR1_OFFSET)
+# define STM32_TIM3_CCR2 (STM32_TIM3_BASE+STM32_GTIM_CCR2_OFFSET)
+# define STM32_TIM3_CCR3 (STM32_TIM3_BASE+STM32_GTIM_CCR3_OFFSET)
+# define STM32_TIM3_CCR4 (STM32_TIM3_BASE+STM32_GTIM_CCR4_OFFSET)
+# define STM32_TIM3_DCR (STM32_TIM3_BASE+STM32_GTIM_DCR_OFFSET)
+# define STM32_TIM3_DMAR (STM32_TIM3_BASE+STM32_GTIM_DMAR_OFFSET)
+#endif
+
+#if STM32_NGTIM > 2
+# define STM32_TIM4_CR1 (STM32_TIM4_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM4_CR2 (STM32_TIM4_BASE+STM32_GTIM_CR2_OFFSET)
+# define STM32_TIM4_SMCR (STM32_TIM4_BASE+STM32_GTIM_SMCR_OFFSET)
+# define STM32_TIM4_DIER (STM32_TIM4_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM4_SR (STM32_TIM4_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM4_EGR (STM32_TIM4_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM4_CCMR1 (STM32_TIM4_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM4_CCMR2 (STM32_TIM4_BASE+STM32_GTIM_CCMR2_OFFSET)
+# define STM32_TIM4_CCER (STM32_TIM4_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM4_CNT (STM32_TIM4_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM4_PSC (STM32_TIM4_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM4_ARR (STM32_TIM4_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM4_CCR1 (STM32_TIM4_BASE+STM32_GTIM_CCR1_OFFSET)
+# define STM32_TIM4_CCR2 (STM32_TIM4_BASE+STM32_GTIM_CCR2_OFFSET)
+# define STM32_TIM4_CCR3 (STM32_TIM4_BASE+STM32_GTIM_CCR3_OFFSET)
+# define STM32_TIM4_CCR4 (STM32_TIM4_BASE+STM32_GTIM_CCR4_OFFSET)
+# define STM32_TIM4_DCR (STM32_TIM4_BASE+STM32_GTIM_DCR_OFFSET)
+# define STM32_TIM4_DMAR (STM32_TIM4_BASE+STM32_GTIM_DMAR_OFFSET)
+#endif
+
+#if STM32_NGTIM > 3
+# define STM32_TIM5_CR1 (STM32_TIM5_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM5_CR2 (STM32_TIM5_BASE+STM32_GTIM_CR2_OFFSET)
+# define STM32_TIM5_SMCR (STM32_TIM5_BASE+STM32_GTIM_SMCR_OFFSET)
+# define STM32_TIM5_DIER (STM32_TIM5_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM5_SR (STM32_TIM5_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM5_EGR (STM32_TIM5_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM5_CCMR1 (STM32_TIM5_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM5_CCMR2 (STM32_TIM5_BASE+STM32_GTIM_CCMR2_OFFSET)
+# define STM32_TIM5_CCER (STM32_TIM5_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM5_CNT (STM32_TIM5_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM5_PSC (STM32_TIM5_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM5_ARR (STM32_TIM5_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM5_CCR1 (STM32_TIM5_BASE+STM32_GTIM_CCR1_OFFSET)
+# define STM32_TIM5_CCR2 (STM32_TIM5_BASE+STM32_GTIM_CCR2_OFFSET)
+# define STM32_TIM5_CCR3 (STM32_TIM5_BASE+STM32_GTIM_CCR3_OFFSET)
+# define STM32_TIM5_CCR4 (STM32_TIM5_BASE+STM32_GTIM_CCR4_OFFSET)
+# define STM32_TIM5_DCR (STM32_TIM5_BASE+STM32_GTIM_DCR_OFFSET)
+# define STM32_TIM5_DMAR (STM32_TIM5_BASE+STM32_GTIM_DMAR_OFFSET)
+# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define STM32_TIM5_OR (STM32_TIM5_BASE+STM32_GTIM_OR_OFFSET)
+# endif
+#endif
+
+/* 16-bit General Timers - TIM9-14 without DMA. Note that (1) these timers
+ * support only a subset of the general timer registers are supported, and
+ * (2) TIM9 and TIM12 differ from the others.
+ */
+
+#if STM32_NGTIMNDMA > 0
+# define STM32_TIM9_CR1 (STM32_TIM9_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM9_CR2 (STM32_TIM9_BASE+STM32_GTIM_CR2_OFFSET)
+# define STM32_TIM9_DIER (STM32_TIM9_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM9_SR (STM32_TIM9_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM9_EGR (STM32_TIM9_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM9_CCMR1 (STM32_TIM9_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM9_CCER (STM32_TIM9_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM9_CNT (STM32_TIM9_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM9_PSC (STM32_TIM9_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM9_ARR (STM32_TIM9_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM9_CCR1 (STM32_TIM9_BASE+STM32_GTIM_CCR1_OFFSET)
+# define STM32_TIM9_CCR2 (STM32_TIM9_BASE+STM32_GTIM_CCR2_OFFSET)
+#endif
+
+#if STM32_NGTIMNDMA > 1
+# define STM32_TIM10_CR1 (STM32_TIM10_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM10_DIER (STM32_TIM10_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM10_SR (STM32_TIM10_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM10_EGR (STM32_TIM10_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM10_CCMR1 (STM32_TIM10_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM10_CCER (STM32_TIM10_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM10_CNT (STM32_TIM10_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM10_PSC (STM32_TIM10_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM10_ARR (STM32_TIM10_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM10_CCR1 (STM32_TIM10_BASE+STM32_GTIM_CCR1_OFFSET)
+#endif
+
+#if STM32_NGTIMNDMA > 2
+# define STM32_TIM11_CR1 (STM32_TIM11_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM11_DIER (STM32_TIM11_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM11_SR (STM32_TIM11_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM11_EGR (STM32_TIM11_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM11_CCMR1 (STM32_TIM11_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM11_CCER (STM32_TIM11_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM11_CNT (STM32_TIM11_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM11_PSC (STM32_TIM11_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM11_ARR (STM32_TIM11_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM11_CCR1 (STM32_TIM11_BASE+STM32_GTIM_CCR1_OFFSET)
+# define STM32_TIM11_OR (STM32_TIM11_BASE+STM32_GTIM_OR_OFFSET)
+#endif
+
+#if STM32_NGTIMNDMA > 3
+# define STM32_TIM12_CR1 (STM32_TIM12_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM12_CR2 (STM32_TIM9_BASE+STM32_GTIM_CR2_OFFSET)
+# define STM32_TIM12_DIER (STM32_TIM12_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM12_SR (STM32_TIM12_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM12_EGR (STM32_TIM12_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM12_CCMR1 (STM32_TIM12_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM12_CCER (STM32_TIM12_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM12_CNT (STM32_TIM12_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM12_PSC (STM32_TIM12_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM12_ARR (STM32_TIM12_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM12_CCR1 (STM32_TIM12_BASE+STM32_GTIM_CCR1_OFFSET)
+# define STM32_TIM12_CCR2 (STM32_TIM12_BASE+STM32_GTIM_CCR2_OFFSET)
+#endif
+
+#if STM32_NGTIMNDMA > 4
+# define STM32_TIM13_CR1 (STM32_TIM13_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM13_DIER (STM32_TIM13_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM13_SR (STM32_TIM13_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM13_EGR (STM32_TIM13_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM13_CCMR1 (STM32_TIM13_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM13_CCER (STM32_TIM13_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM13_CNT (STM32_TIM13_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM13_PSC (STM32_TIM13_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM13_ARR (STM32_TIM13_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM13_CCR1 (STM32_TIM13_BASE+STM32_GTIM_CCR1_OFFSET)
+#endif
+
+#if STM32_NGTIMNDMA > 5
+# define STM32_TIM14_CR1 (STM32_TIM14_BASE+STM32_GTIM_CR1_OFFSET)
+# define STM32_TIM14_DIER (STM32_TIM14_BASE+STM32_GTIM_DIER_OFFSET)
+# define STM32_TIM14_SR (STM32_TIM14_BASE+STM32_GTIM_SR_OFFSET)
+# define STM32_TIM14_EGR (STM32_TIM14_BASE+STM32_GTIM_EGR_OFFSET)
+# define STM32_TIM14_CCMR1 (STM32_TIM14_BASE+STM32_GTIM_CCMR1_OFFSET)
+# define STM32_TIM14_CCER (STM32_TIM14_BASE+STM32_GTIM_CCER_OFFSET)
+# define STM32_TIM14_CNT (STM32_TIM14_BASE+STM32_GTIM_CNT_OFFSET)
+# define STM32_TIM14_PSC (STM32_TIM14_BASE+STM32_GTIM_PSC_OFFSET)
+# define STM32_TIM14_ARR (STM32_TIM14_BASE+STM32_GTIM_ARR_OFFSET)
+# define STM32_TIM14_CCR1 (STM32_TIM14_BASE+STM32_GTIM_CCR1_OFFSET)
+#endif
+
+/* Basic Timers - TIM6 and TIM7 */
+
+#if STM32_NBTIM > 0
+# define STM32_TIM6_CR1 (STM32_TIM6_BASE+STM32_BTIM_CR1_OFFSET)
+# define STM32_TIM6_CR2 (STM32_TIM6_BASE+STM32_BTIM_CR2_OFFSET)
+# define STM32_TIM6_DIER (STM32_TIM6_BASE+STM32_BTIM_DIER_OFFSET)
+# define STM32_TIM6_SR (STM32_TIM6_BASE+STM32_BTIM_SR_OFFSET)
+# define STM32_TIM6_EGR (STM32_TIM6_BASE+STM32_BTIM_EGR_OFFSET)
+# define STM32_TIM6_CNT (STM32_TIM6_BASE+STM32_BTIM_CNT_OFFSET)
+# define STM32_TIM6_PSC (STM32_TIM6_BASE+STM32_BTIM_PSC_OFFSET)
+# define STM32_TIM6_ARR (STM32_TIM6_BASE+STM32_BTIM_ARR_OFFSET)
+#endif
+
+#if STM32_NBTIM > 1
+# define STM32_TIM7_CR1 (STM32_TIM7_BASE+STM32_BTIM_CR1_OFFSET)
+# define STM32_TIM7_CR2 (STM32_TIM7_BASE+STM32_BTIM_CR2_OFFSET)
+# define STM32_TIM7_DIER (STM32_TIM7_BASE+STM32_BTIM_DIER_OFFSET)
+# define STM32_TIM7_SR (STM32_TIM7_BASE+STM32_BTIM_SR_OFFSET)
+# define STM32_TIM7_EGR (STM32_TIM7_BASE+STM32_BTIM_EGR_OFFSET)
+# define STM32_TIM7_CNT (STM32_TIM7_BASE+STM32_BTIM_CNT_OFFSET)
+# define STM32_TIM7_PSC (STM32_TIM7_BASE+STM32_BTIM_PSC_OFFSET)
+# define STM32_TIM7_ARR (STM32_TIM7_BASE+STM32_BTIM_ARR_OFFSET)
+#endif
+
+/* Register Bitfield Definitions ********************************************************************/
+
+/* Control register 1 */
+
+#define ATIM_CR1_CEN (1 << 0) /* Bit 0: Counter enable */
+#define ATIM_CR1_UDIS (1 << 1) /* Bit 1: Update disable */
+#define ATIM_CR1_URS (1 << 2) /* Bit 2: Update request source */
+#define ATIM_CR1_OPM (1 << 3) /* Bit 3: One pulse mode */
+#define ATIM_CR1_DIR (1 << 4) /* Bit 4: Direction */
+#define ATIM_CR1_CMS_SHIFT (5) /* Bits 6-5: Center-aligned mode selection */
+#define ATIM_CR1_CMS_MASK (3 << ATIM_CR1_CMS_SHIFT)
+# define ATIM_CR1_EDGE (0 << ATIM_CR1_CMS_SHIFT) /* 00: Edge-aligned mode */
+# define ATIM_CR1_CENTER1 (1 << ATIM_CR1_CMS_SHIFT) /* 01: Center-aligned mode 1 */
+# define ATIM_CR1_CENTER2 (2 << ATIM_CR1_CMS_SHIFT) /* 10: Center-aligned mode 2 */
+# define ATIM_CR1_CENTER3 (3 << ATIM_CR1_CMS_SHIFT) /* 11: Center-aligned mode 3 */
+#define ATIM_CR1_ARPE (1 << 7) /* Bit 7: Auto-reload preload enable */
+#define ATIM_CR1_CKD_SHIFT (8) /* Bits 9-8: Clock division */
+#define ATIM_CR1_CKD_MASK (3 << ATIM_CR1_CKD_SHIFT)
+# define ATIM_CR1_TCKINT (0 << ATIM_CR1_CKD_SHIFT) /* 00: tDTS=tCK_INT */
+# define ATIM_CR1_2TCKINT (1 << ATIM_CR1_CKD_SHIFT) /* 01: tDTS=2*tCK_INT */
+# define ATIM_CR1_4TCKINT (2 << ATIM_CR1_CKD_SHIFT) /* 10: tDTS=4*tCK_INT */
+
+/* Control register 2 */
+
+#define ATIM_CR2_CCPC (1 << 0) /* Bit 0: Capture/Compare Preloaded Control */
+#define ATIM_CR2_CCUS (1 << 2) /* Bit 2: Capture/Compare Control Update Selection */
+#define ATIM_CR2_CCDS (1 << 3) /* Bit 3: Capture/Compare DMA Selection */
+#define ATIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection */
+#define ATIM_CR2_MMS_MASK (7 << ATIM_CR2_MMS_SHIFT)
+#define ATIM_CR2_OC1REF (4 << ATIM_CR2_MMS_SHIFT) /* 100: Compare OC1REF is TRGO */
+#define ATIM_CR2_OC2REF (5 << ATIM_CR2_MMS_SHIFT) /* 101: Compare OC2REF is TRGO */
+#define ATIM_CR2_OC3REF (6 << ATIM_CR2_MMS_SHIFT) /* 110: Compare OC3REF is TRGO */
+#define ATIM_CR2_OC4REF (7 << ATIM_CR2_MMS_SHIFT) /* 111: Compare OC4REF is TRGO */
+#define ATIM_CR2_TI1S (1 << 7) /* Bit 7: TI1 Selection */
+#define ATIM_CR2_OIS1 (1 << 8) /* Bit 8: Output Idle state 1 (OC1 output) */
+#define ATIM_CR2_OIS1N (1 << 9) /* Bit 9: Output Idle state 1 (OC1N output) */
+#define ATIM_CR2_OIS2 (1 << 10) /* Bit 10: Output Idle state 2 (OC2 output) */
+#define ATIM_CR2_OIS2N (1 << 11) /* Bit 11: Output Idle state 2 (OC2N output) */
+#define ATIM_CR2_OIS3 (1 << 12) /* Bit 12: Output Idle state 3 (OC3 output) */
+#define ATIM_CR2_OIS3N (1 << 13) /* Bit 13: Output Idle state 3 (OC3N output) */
+#define ATIM_CR2_OIS4 (1 << 14) /* Bit 14: Output Idle state 4 (OC4 output) */
+
+/* Slave mode control register */
+
+#define ATIM_SMCR_SMS_SHIFT (0) /* Bits 0-2: Slave mode selection */
+#define ATIM_SMCR_SMS_MASK (7 << ATIM_SMCR_SMS_SHIFT)
+# define ATIM_SMCR_DISAB (0 << ATIM_SMCR_SMS_SHIFT) /* 000: Slave mode disabled */
+# define ATIM_SMCR_ENCMD1 (1 << ATIM_SMCR_SMS_SHIFT) /* 001: Encoder mode 1 */
+# define ATIM_SMCR_ENCMD2 (2 << ATIM_SMCR_SMS_SHIFT) /* 010: Encoder mode 2 */
+# define ATIM_SMCR_ENCMD3 (3 << ATIM_SMCR_SMS_SHIFT) /* 011: Encoder mode 3 */
+# define ATIM_SMCR_RESET (4 << ATIM_SMCR_SMS_SHIFT) /* 100: Reset Mode */
+# define ATIM_SMCR_GATED (5 << ATIM_SMCR_SMS_SHIFT) /* 101: Gated Mode */
+# define ATIM_SMCR_TRIGGER (6 << ATIM_SMCR_SMS_SHIFT) /* 110: Trigger Mode */
+# define ATIM_SMCR_EXTCLK1 (7 << ATIM_SMCR_SMS_SHIFT) /* 111: External Clock Mode 1 */
+#define ATIM_SMCR_TS_SHIFT (4) /* Bits 4-6: Trigger selection */
+#define ATIM_SMCR_TS_MASK (7 << ATIM_SMCR_TS_SHIFT)
+# define ATIM_SMCR_ITR0 (0 << ATIM_SMCR_TS_SHIFT) /* 000: Internal trigger 0 (ITR0) */
+# define ATIM_SMCR_ITR1 (1 << ATIM_SMCR_TS_SHIFT) /* 001: Internal trigger 1 (ITR1) */
+# define ATIM_SMCR_ITR2 (2 << ATIM_SMCR_TS_SHIFT) /* 010: Internal trigger 2 (ITR2) */
+# define ATIM_SMCR_ITR3 (3 << ATIM_SMCR_TS_SHIFT) /* 011: Internal trigger 3 (ITR3) */
+# define ATIM_SMCR_T1FED (4 << ATIM_SMCR_TS_SHIFT) /* 100: TI1 Edge Detector (TI1F_ED) */
+# define ATIM_SMCR_TI1FP1 (5 << ATIM_SMCR_TS_SHIFT) /* 101: Filtered Timer Input 1 (TI1FP1) */
+# define ATIM_SMCR_T12FP2 (6 << ATIM_SMCR_TS_SHIFT) /* 110: Filtered Timer Input 2 (TI2FP2) */
+# define ATIM_SMCR_ETRF (7 << ATIM_SMCR_TS_SHIFT) /* 111: External Trigger input (ETRF) */
+#define ATIM_SMCR_MSM (1 << 7) /* Bit 7: Master/slave mode */
+#define ATIM_SMCR_ETF_SHIFT (8) /* Bits 8-11: External trigger filter */
+#define ATIM_SMCR_ETF_MASK (0x0f << ATIM_SMCR_ETF_SHIFT)
+# define ATIM_SMCR_NOFILT (0 << ATIM_SMCR_ETF_SHIFT) /* 0000: No filter, sampling is done at fDTS */
+# define ATIM_SMCR_FCKINT2 (1 << ATIM_SMCR_ETF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */
+# define ATIM_SMCR_FCKINT4 (2 << ATIM_SMCR_ETF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */
+# define ATIM_SMCR_FCKINT8 (3 << ATIM_SMCR_ETF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */
+# define ATIM_SMCR_FDTSd26 (4 << ATIM_SMCR_ETF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */
+# define ATIM_SMCR_FDTSd28 (5 << ATIM_SMCR_ETF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */
+# define ATIM_SMCR_FDTSd46 (6 << ATIM_SMCR_ETF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */
+# define ATIM_SMCR_FDTSd48 (7 << ATIM_SMCR_ETF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */
+# define ATIM_SMCR_FDTSd86 (8 << ATIM_SMCR_ETF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */
+# define ATIM_SMCR_FDTSd88 (9 << ATIM_SMCR_ETF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */
+# define ATIM_SMCR_FDTSd165 (10 << ATIM_SMCR_ETF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */
+# define ATIM_SMCR_FDTSd166 (11 << ATIM_SMCR_ETF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */
+# define ATIM_SMCR_FDTSd168 (12 << ATIM_SMCR_ETF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */
+# define ATIM_SMCR_FDTSd325 (13 << ATIM_SMCR_ETF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */
+# define ATIM_SMCR_FDTSd326 (14 << ATIM_SMCR_ETF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */
+# define ATIM_SMCR_FDTSd328 (15 << ATIM_SMCR_ETF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */
+#define ATIM_SMCR_ETPS_SHIFT (12) /* Bits 12-13: External trigger prescaler */
+#define ATIM_SMCR_ETPS_MASK (3 << ATIM_SMCR_ETPS_SHIFT)
+# define ATIM_SMCR_PSCOFF (0 << ATIM_SMCR_ETPS_SHIFT) /* 00: Prescaler OFF */
+# define ATIM_SMCR_ETRPd2 (1 << ATIM_SMCR_ETPS_SHIFT) /* 01: ETRP frequency divided by 2 */
+# define ATIM_SMCR_ETRPd4 (2 << ATIM_SMCR_ETPS_SHIFT) /* 10: ETRP frequency divided by 4 */
+# define ATIM_SMCR_ETRPd8 (3 << ATIM_SMCR_ETPS_SHIFT) /* 11: ETRP frequency divided by 8 */
+#define ATIM_SMCR_ECE (1 << 14) /* Bit 14: External clock enable */
+#define ATIM_SMCR_ETP (1 << 15) /* Bit 15: External trigger polarity */
+
+/* DMA/Interrupt enable register */
+
+#define ATIM_DIER_UIE (1 << 0) /* Bit 0: Update interrupt enable */
+#define ATIM_DIER_CC1IE (1 << 1) /* Bit 1: Capture/Compare 1 interrupt enable */
+#define ATIM_DIER_CC2IE (1 << 2) /* Bit 2: Capture/Compare 2 interrupt enable */
+#define ATIM_DIER_CC3IE (1 << 3) /* Bit 3: Capture/Compare 3 interrupt enable */
+#define ATIM_DIER_CC4IE (1 << 4) /* Bit 4: Capture/Compare 4 interrupt enable */
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ATIM_DIER_COMIE (1 << 5) /* Bit 5: COM interrupt enable */
+#endif
+
+#define ATIM_DIER_TIE (1 << 6) /* Bit 6: Trigger interrupt enable */
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ATIM_DIER_BIE (1 << 7) /* Bit 7: Break interrupt enable */
+#endif
+
+#define ATIM_DIER_UDE (1 << 8) /* Bit 8: Update DMA request enable */
+#define ATIM_DIER_CC1DE (1 << 9) /* Bit 9: Capture/Compare 1 DMA request enable */
+#define ATIM_DIER_CC2DE (1 << 10) /* Bit 10: Capture/Compare 2 DMA request enable */
+#define ATIM_DIER_CC3DE (1 << 11) /* Bit 11: Capture/Compare 3 DMA request enable */
+#define ATIM_DIER_CC4DE (1 << 12) /* Bit 12: Capture/Compare 4 DMA request enable */
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ATIM_DIER_COMDE (1 << 13) /* Bit 13: COM DMA request enable */
+#endif
+
+#define ATIM_DIER_TDE (1 << 14) /* Bit 14: Trigger DMA request enable */
+
+/* Status register */
+
+#define ATIM_SR_UIF (1 << 0) /* Bit 0: Update interrupt Flag */
+#define ATIM_SR_CC1IF (1 << 1) /* Bit 1: Capture/Compare 1 interrupt Flag */
+#define ATIM_SR_CC2IF (1 << 2) /* Bit 2: Capture/Compare 2 interrupt Flag */
+#define ATIM_SR_CC3IF (1 << 3) /* Bit 3: Capture/Compare 3 interrupt Flag */
+#define ATIM_SR_CC4IF (1 << 4) /* Bit 4: Capture/Compare 4 interrupt Flag */
+#define ATIM_SR_COMIF (1 << 5) /* Bit 5: COM interrupt Flag */
+#define ATIM_SR_TIF (1 << 6) /* Bit 6: Trigger interrupt Flag */
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ATIM_SR_BIF (1 << 7) /* Bit 7: Break interrupt Flag */
+#endif
+
+#define ATIM_SR_CC1OF (1 << 9) /* Bit 9: Capture/Compare 1 Overcapture Flag */
+#define ATIM_SR_CC2OF (1 << 10) /* Bit 10: Capture/Compare 2 Overcapture Flag */
+#define ATIM_SR_CC3OF (1 << 11) /* Bit 11: Capture/Compare 3 Overcapture Flag */
+#define ATIM_SR_CC4OF (1 << 12) /* Bit 12: Capture/Compare 4 Overcapture Flag */
+
+/* Event generation register */
+
+#define ATIM_EGR_UG (1 << 0) /* Bit 0: Update Generation */
+#define ATIM_EGR_CC1G (1 << 1) /* Bit 1: Capture/Compare 1 Generation */
+#define ATIM_EGR_CC2G (1 << 2) /* Bit 2: Capture/Compare 2 Generation */
+#define ATIM_EGR_CC3G (1 << 3) /* Bit 3: Capture/Compare 3 Generation */
+#define ATIM_EGR_CC4G (1 << 4) /* Bit 4: Capture/Compare 4 Generation */
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ATIM_EGR_COMG (1 << 5) /* Bit 5: Capture/Compare Control Update Generation */
+#endif
+
+#define ATIM_EGR_TG (1 << 6) /* Bit 6: Trigger Generation */
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ATIM_EGR_BG (1 << 7) /* Bit 7: Break Generation */
+#endif
+
+/* Capture/compare mode register 1 -- Output compare mode */
+
+#define ATIM_CCMR1_CC1S_SHIFT (0) /* Bits 1-0: Capture/Compare 1 Selection */
+#define ATIM_CCMR1_CC1S_MASK (3 << ATIM_CCMR1_CC1S_SHIFT)
+ /* (See common (unshifted) bit field definitions below) */
+#define ATIM_CCMR1_OC1FE (1 << 2) /* Bit 2: Output Compare 1 Fast enable */
+#define ATIM_CCMR1_OC1PE (1 << 3) /* Bit 3: Output Compare 1 Preload enable */
+#define ATIM_CCMR1_OC1M_SHIFT (4) /* Bits 6-4: Output Compare 1 Mode */
+#define ATIM_CCMR1_OC1M_MASK (7 << ATIM_CCMR1_OC1M_SHIFT)
+ /* (See common (unshifted) bit field definitions below) */
+#define ATIM_CCMR1_OC1CE (1 << 7) /* Bit 7: Output Compare 1Clear Enable */
+#define ATIM_CCMR1_CC2S_SHIFT (8) /* Bits 8-9: Capture/Compare 2 Selection */
+#define ATIM_CCMR1_CC2S_MASK (3 << ATIM_CCMR1_CC2S_SHIFT)
+ /* (See common (unshifted) bit field definitions below) */
+#define ATIM_CCMR1_OC2FE (1 << 10) /* Bit 10: Output Compare 2 Fast enable */
+#define ATIM_CCMR1_OC2PE (1 << 11) /* Bit 11: Output Compare 2 Preload enable */
+#define ATIM_CCMR1_OC2M_SHIFT (12) /* Bits 14-12: Output Compare 2 Mode */
+#define ATIM_CCMR1_OC2M_MASK (7 << ATIM_CCMR1_OC2M_SHIFT)
+ /* (See common (unshifted) bit field definitions below) */
+#define ATIM_CCMR1_OC2CE (1 << 15) /* Bit 15: Output Compare 2 Clear Enable */
+
+/* Common CCMR (unshifted) Capture/Compare Selection bit-field definitions */
+
+#define ATIM_CCMR_CCS_CCOUT (0) /* 00: CCx channel output */
+#define ATIM_CCMR_CCS_CCIN1 (1) /* 01: CCx channel input, ICx is TIx */
+#define ATIM_CCMR_CCS_CCIN2 (2) /* 10: CCx channel input, ICx is TIy */
+#define ATIM_CCMR_CCS_CCINTRC (3) /* 11: CCx channel input, ICx is TRC */
+
+/* Common CCMR (unshifted) Compare Mode bit field definitions */
+
+#define ATIM_CCMR_MODE_FRZN (0) /* 000: Frozen */
+#define ATIM_CCMR_MODE_CHACT (1) /* 001: Channel x active on match */
+#define ATIM_CCMR_MODE_CHINACT (2) /* 010: Channel x inactive on match */
+#define ATIM_CCMR_MODE_OCREFTOG (3) /* 011: OCxREF toggle ATIM_CNT=ATIM_CCRx */
+#define ATIM_CCMR_MODE_OCREFLO (4) /* 100: OCxREF forced low */
+#define ATIM_CCMR_MODE_OCREFHI (5) /* 101: OCxREF forced high */
+#define ATIM_CCMR_MODE_PWM1 (6) /* 110: PWM mode 1 */
+#define ATIM_CCMR_MODE_PWM2 (7) /* 111: PWM mode 2 */
+
+/* Capture/compare mode register 1 -- Input capture mode */
+
+ /* Bits 1-0:(same as output compare mode) */
+#define ATIM_CCMR1_IC1PSC_SHIFT (2) /* Bits 3-2: Input Capture 1 Prescaler */
+#define ATIM_CCMR1_IC1PSC_MASK (3 << ATIM_CCMR1_IC1PSC_SHIFT)
+ /* (See common (unshifted) bit field definitions below) */
+#define ATIM_CCMR1_IC1F_SHIFT (4) /* Bits 7-4: Input Capture 1 Filter */
+#define ATIM_CCMR1_IC1F_MASK (0x0f << ATIM_CCMR1_IC1F_SHIFT)
+ /* (See common (unshifted) bit field definitions below) */
+ /* Bits 9:8 (same as output compare mode) */
+#define ATIM_CCMR1_IC2PSC_SHIFT (10) /* Bits 11:10: Input Capture 2 Prescaler */
+#define ATIM_CCMR1_IC2PSC_MASK (3 << ATIM_CCMR1_IC2PSC_SHIFT)
+ /* (See common (unshifted) bit field definitions below) */
+#define ATIM_CCMR1_IC2F_SHIFT (12) /* Bits 15-12: Input Capture 2 Filter */
+#define ATIM_CCMR1_IC2F_MASK (0x0f << ATIM_CCMR1_IC2F_SHIFT)
+ /* (See common (unshifted) bit field definitions below) */
+
+/* Common CCMR (unshifted) Input Capture Prescaler bit-field definitions */
+
+#define ATIM_CCMR_ICPSC_NOPSC (0) /* 00: no prescaler, capture each edge */
+#define ATIM_CCMR_ICPSC_EVENTS2 (1) /* 01: capture once every 2 events */
+#define ATIM_CCMR_ICPSC_EVENTS4 (2) /* 10: capture once every 4 events */
+#define ATIM_CCMR_ICPSC_EVENTS8 (3) /* 11: capture once every 8 events */
+
+/* Common CCMR (unshifted) Input Capture Filter bit-field definitions */
+
+#define ATIM_CCMR_ICF_NOFILT (0) /* 0000: No filter, sampling at fDTS */
+#define ATIM_CCMR_ICF_FCKINT2 (1) /* 0001: fSAMPLING=fCK_INT, N=2 */
+#define ATIM_CCMR_ICF_FCKINT4 (2) /* 0010: fSAMPLING=fCK_INT, N=4 */
+#define ATIM_CCMR_ICF_FCKINT8 (3) /* 0011: fSAMPLING=fCK_INT, N=8 */
+#define ATIM_CCMR_ICF_FDTSd26 (4) /* 0100: fSAMPLING=fDTS/2, N=6 */
+#define ATIM_CCMR_ICF_FDTSd28 (5) /* 0101: fSAMPLING=fDTS/2, N=8 */
+#define ATIM_CCMR_ICF_FDTSd46 (6) /* 0110: fSAMPLING=fDTS/4, N=6 */
+#define ATIM_CCMR_ICF_FDTSd48 (7) /* 0111: fSAMPLING=fDTS/4, N=8 */
+#define ATIM_CCMR_ICF_FDTSd86 (8) /* 1000: fSAMPLING=fDTS/8, N=6 */
+#define ATIM_CCMR_ICF_FDTSd88 (9) /* 1001: fSAMPLING=fDTS/8, N=8 */
+#define ATIM_CCMR_ICF_FDTSd165 (10) /* 1010: fSAMPLING=fDTS/16, N=5 */
+#define ATIM_CCMR_ICF_FDTSd166 (11) /* 1011: fSAMPLING=fDTS/16, N=6 */
+#define ATIM_CCMR_ICF_FDTSd168 (12) /* 1100: fSAMPLING=fDTS/16, N=8 */
+#define ATIM_CCMR_ICF_FDTSd325 (13) /* 1101: fSAMPLING=fDTS/32, N=5 */
+#define ATIM_CCMR_ICF_FDTSd326 (14) /* 1110: fSAMPLING=fDTS/32, N=6 */
+#define ATIM_CCMR_ICF_FDTSd328 (15) /* 1111: fSAMPLING=fDTS/32, N=8 */
+
+/* Capture/compare mode register 2 - Output Compare mode */
+
+#define ATIM_CCMR2_CC3S_SHIFT (0) /* Bits 1-0: Capture/Compare 3 Selection */
+#define ATIM_CCMR2_CC3S_MASK (3 << ATIM_CCMR2_CC3S_SHIFT)
+ /* (See common (unshifted) bit field definitions above) */
+#define ATIM_CCMR2_OC3FE (1 << 2) /* Bit 2: Output Compare 3 Fast enable */
+#define ATIM_CCMR2_OC3PE (1 << 3) /* Bit 3: Output Compare 3 Preload enable */
+#define ATIM_CCMR2_OC3M_SHIFT (4) /* Bits 6-4: Output Compare 3 Mode */
+#define ATIM_CCMR2_OC3M_MASK (7 << ATIM_CCMR2_OC3M_SHIFT)
+ /* (See common (unshifted) bit field definitions above) */
+#define ATIM_CCMR2_OC3CE (1 << 7) /* Bit 7: Output Compare 3 Clear Enable */
+#define ATIM_CCMR2_CC4S_SHIFT (8) /* Bits 9-8: Capture/Compare 4 Selection */
+#define ATIM_CCMR2_CC4S_MASK (3 << ATIM_CCMR2_CC4S_SHIFT)
+ /* (See common (unshifted) bit field definitions above) */
+#define ATIM_CCMR2_OC4FE (1 << 10) /* Bit 10: Output Compare 4 Fast enable */
+#define ATIM_CCMR2_OC4PE (1 << 11) /* Bit 11: Output Compare 4 Preload enable */
+#define ATIM_CCMR2_OC4M_SHIFT (12) /* Bits 14-12: Output Compare 4 Mode */
+#define ATIM_CCMR2_OC4M_MASK (7 << ATIM_CCMR2_OC4M_SHIFT)
+ /* (See common (unshifted) bit field definitions above) */
+#define ATIM_CCMR2_OC4CE (1 << 15) /* Bit 15: Output Compare 4 Clear Enable */
+
+/* Capture/compare mode register 2 - Input Capture Mode */
+
+ /* Bits 1-0:(same as output compare mode) */
+#define ATIM_CCMR2_IC3PSC_SHIFT (2) /* Bits 3-2: Input Capture 3 Prescaler */
+#define ATIM_CCMR1_IC3PSC_MASK (3 << ATIM_CCMR2_IC3PSC_SHIFT)
+ /* (See common (unshifted) bit field definitions above) */
+#define ATIM_CCMR2_IC3F_SHIFT (4) /* Bits 7-4: Input Capture 3 Filter */
+#define ATIM_CCMR2_IC3F_MASK (0x0f << ATIM_CCMR2_IC3F_SHIFT)
+ /* (See common (unshifted) bit field definitions above) */
+ /* Bits 9:8 (same as output compare mode) */
+#define ATIM_CCMR2_IC4PSC_SHIFT (10) /* Bits 11:10: Input Capture 4 Prescaler */
+#define ATIM_CCMR2_IC4PSC_MASK (3 << ATIM_CCMR2_IC4PSC_SHIFT)
+ /* (See common (unshifted) bit field definitions above) */
+#define ATIM_CCMR2_IC4F_SHIFT (12) /* Bits 15-12: Input Capture 4 Filter */
+#define ATIM_CCMR2_IC4F_MASK (0x0f << ATIM_CCMR2_IC4F_SHIFT)
+ /* (See common (unshifted) bit field definitions above) */
+
+/* Capture/compare enable register */
+
+#define ATIM_CCER_CC1E (1 << 0) /* Bit 0: Capture/Compare 1 output enable */
+#define ATIM_CCER_CC1P (1 << 1) /* Bit 1: Capture/Compare 1 output Polarity */
+#define ATIM_CCER_CC1NE (1 << 2) /* Bit 2: Capture/Compare 1 Complementary output enable */
+#define ATIM_CCER_CC1NP (1 << 3) /* Bit 3: Capture/Compare 1 Complementary output Polarity */
+#define ATIM_CCER_CC2E (1 << 4) /* Bit 4: Capture/Compare 2 output enable */
+#define ATIM_CCER_CC2P (1 << 5) /* Bit 5: Capture/Compare 2 output Polarity */
+#define ATIM_CCER_CC2NE (1 << 6) /* Bit 6: Capture/Compare 2 Complementary output enable */
+#define ATIM_CCER_CC2NP (1 << 7) /* Bit 7: Capture/Compare 2 Complementary output Polarity */
+#define ATIM_CCER_CC3E (1 << 8) /* Bit 8: Capture/Compare 3 output enable */
+#define ATIM_CCER_CC3P (1 << 9) /* Bit 9: Capture/Compare 3 output Polarity */
+#define ATIM_CCER_CC3NE (1 << 10) /* Bit 10: Capture/Compare 3 Complementary output enable */
+#define ATIM_CCER_CC3NP (1 << 11) /* Bit 11: Capture/Compare 3 Complementary output Polarity */
+#define ATIM_CCER_CC4E (1 << 12) /* Bit 12: Capture/Compare 4 output enable */
+#define ATIM_CCER_CC4P (1 << 13) /* Bit 13: Capture/Compare 4 output Polarity */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define ATIM_CCER_CC4NP (1 << 15) /* Bit 15: Capture/Compare 4 output Polarity */
+#endif
+
+/* Repetition counter register */
+
+#define ATIM_RCR_REP_SHIFT (0) /* Bits 7-0: Repetition Counter Value */
+#define ATIM_RCR_REP_MASK (0xff << ATIM_RCR_REP_SHIFT)
+
+#define ATIM_RCR_REP_MAX 128
+
+/* Break and dead-time register */
+
+#define ATIM_BDTR_DTG_SHIFT (0) /* Bits 7:0 [7:0]: Dead-Time Generator set-up */
+#define ATIM_BDTR_DTG_MASK (0xff << ATIM_BDTR_DTG_SHIFT)
+#define ATIM_BDTR_LOCK_SHIFT (8) /* Bits 9:8 [1:0]: Lock Configuration */
+#define ATIM_BDTR_LOCK_MASK (3 << ATIM_BDTR_LOCK_SHIFT)
+# define ATIM_BDTR_LOCKOFF (0 << ATIM_BDTR_LOCK_SHIFT) /* 00: LOCK OFF - No bit is write protected */
+# define ATIM_BDTR_LOCK1 (1 << ATIM_BDTR_LOCK_SHIFT) /* 01: LOCK Level 1 protection */
+# define ATIM_BDTR_LOCK2 (2 << ATIM_BDTR_LOCK_SHIFT) /* 10: LOCK Level 2 protection */
+# define ATIM_BDTR_LOCK3 (3 << ATIM_BDTR_LOCK_SHIFT) /* 11: LOCK Level 3 protection */ */
+#define ATIM_BDTR_OSSI (1 << 10) /* Bit 10: Off-State Selection for Idle mode */
+#define ATIM_BDTR_OSSR (1 << 11) /* Bit 11: Off-State Selection for Run mode */
+#define ATIM_BDTR_BKE (1 << 12) /* Bit 12: Break enable */
+#define ATIM_BDTR_BKP (1 << 13) /* Bit 13: Break Polarity */
+#define ATIM_BDTR_AOE (1 << 14) /* Bit 14: Automatic Output enable */
+#define ATIM_BDTR_MOE (1 << 15) /* Bit 15: Main Output enable */
+
+/* DMA control register */
+
+#define ATIM_DCR_DBL_SHIFT (8) /* Bits 12-8: DMA Burst Length */
+#define ATIM_DCR_DBL_MASK (0x1f << ATIM_DCR_DBL_SHIFT)
+# define ATIM_DCR_DBL(n) (((n)-1) << ATIM_DCR_DBL_SHIFT) /* n transfers, n = 1..18 */
+#define ATIM_DCR_DBA_SHIFT (0) /* Bits 4-0: DMA Base Address */
+#define ATIM_DCR_DBA_MASK (0x1f << ATIM_DCR_DBA_SHIFT)
+
+/* Control register 1 (TIM2-5 and TIM9-14) */
+
+#define GTIM_CR1_CEN (1 << 0) /* Bit 0: Counter enable */
+#define GTIM_CR1_UDIS (1 << 1) /* Bit 1: Update Disable */
+#define GTIM_CR1_URS (1 << 2) /* Bit 2: Update Request Source */
+#define GTIM_CR1_OPM (1 << 3) /* Bit 3: One Pulse Mode (TIM2-5, 9, and 12 only) */
+#define GTIM_CR1_DIR (1 << 4) /* Bit 4: Direction (TIM2-5 only) */
+#define GTIM_CR1_CMS_SHIFT (5) /* Bits 6-5: Center-aligned Mode Selection (TIM2-5 only) */
+#define GTIM_CR1_CMS_MASK (3 << GTIM_CR1_CMS_SHIFT)
+# define GTIM_CR1_EDGE (0 << GTIM_CR1_CMS_SHIFT) /* 00: Edge-aligned mode. */
+# define GTIM_CR1_CENTER1 (1 << GTIM_CR1_CMS_SHIFT) /* 01: Center-aligned mode 1 */
+# define GTIM_CR1_CENTER2 (2 << GTIM_CR1_CMS_SHIFT) /* 10: Center-aligned mode 2 */
+# define GTIM_CR1_CENTER3 (3 << GTIM_CR1_CMS_SHIFT) /* 11: Center-aligned mode 3 */
+#define GTIM_CR1_ARPE (1 << 7) /* Bit 7: Auto-Reload Preload enable */
+#define GTIM_CR1_CKD_SHIFT (8) /* Bits 9-8: Clock Division */
+#define GTIM_CR1_CKD_MASK (3 << GTIM_CR1_CKD_SHIFT)
+# define GTIM_CR1_TCKINT (0 << GTIM_CR1_CKD_SHIFT) /* 00: tDTS = tCK_INT */
+# define GTIM_CR1_2TCKINT (1 << GTIM_CR1_CKD_SHIFT) /* 01: tDTS = 2 x tCK_INT */
+# define GTIM_CR1_4TCKINT (2 << GTIM_CR1_CKD_SHIFT) /* 10: tDTS = 4 x tCK_INT */
+
+/* Control register 2 (TIM2-5 and TIM9/12 only) */
+
+#define GTIM_CR2_CCDS (1 << 3) /* Bit 3: Capture/Compare DMA Selection (TIM2-5 only) */
+#define GTIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection */
+#define GTIM_CR2_MMS_MASK (7 << GTIM_CR2_MMS_SHIFT)
+# define GTIM_CR2_RESET (0 << GTIM_CR2_MMS_SHIFT) /* 000: Reset */
+# define GTIM_CR2_ENAB (1 << GTIM_CR2_MMS_SHIFT) /* 001: Enable */
+# define GTIM_CR2_UPDT (2 << GTIM_CR2_MMS_SHIFT) /* 010: Update */
+# define GTIM_CR2_CMPP (3 << GTIM_CR2_MMS_SHIFT) /* 011: Compare Pulse */
+# define GTIM_CR2_CMP1 (4 << GTIM_CR2_MMS_SHIFT) /* 100: Compare - OC1REF signal is used as trigger output (TRGO) */
+# define GTIM_CR2_CMP2 (5 << GTIM_CR2_MMS_SHIFT) /* 101: Compare - OC2REF signal is used as trigger output (TRGO) */
+# define GTIM_CR2_CMP3 (6 << GTIM_CR2_MMS_SHIFT) /* 110: Compare - OC3REF signal is used as trigger output (TRGO, TIM2-5 only) */
+# define GTIM_CR2_CMP4 (7 << GTIM_CR2_MMS_SHIFT) /* 111: Compare - OC4REF signal is used as trigger output (TRGO, TIM2-5 only) */
+#define GTIM_CR2_TI1S (1 << 7) /* Bit 7: TI1 Selection */
+
+/* Slave mode control register (TIM2-5 only) */
+
+#define GTIM_SMCR_SMS_SHIFT (0) /* Bits 2-0: Slave Mode Selection */
+#define GTIM_SMCR_SMS_MASK (7 << GTIM_SMCR_SMS_SHIFT)
+# define GTIM_SMCR_DISAB (0 << GTIM_SMCR_SMS_SHIFT) /* 000: Slave mode disabled */
+# define GTIM_SMCR_ENCMD1 (1 << GTIM_SMCR_SMS_SHIFT) /* 001: Encoder mode 1 */
+# define GTIM_SMCR_ENCMD2 (2 << GTIM_SMCR_SMS_SHIFT) /* 010: Encoder mode 2 */
+# define GTIM_SMCR_ENCMD3 (3 << GTIM_SMCR_SMS_SHIFT) /* 011: Encoder mode 3 */
+# define GTIM_SMCR_RESET (4 << GTIM_SMCR_SMS_SHIFT) /* 100: Reset Mode */
+# define GTIM_SMCR_GATED (5 << GTIM_SMCR_SMS_SHIFT) /* 101: Gated Mode */
+# define GTIM_SMCR_TRIGGER (6 << GTIM_SMCR_SMS_SHIFT) /* 110: Trigger Mode */
+# define GTIM_SMCR_EXTCLK1 (7 << GTIM_SMCR_SMS_SHIFT) /* 111: External Clock Mode 1 */
+#define GTIM_SMCR_TS_SHIFT (4) /* Bits 6-4: Trigger Selection */
+#define GTIM_SMCR_TS_MASK (7 << GTIM_SMCR_TS_SHIFT)
+# define GTIM_SMCR_ITR0 (0 << GTIM_SMCR_TS_SHIFT) /* 000: Internal Trigger 0 (ITR0). TIM1 */
+# define GTIM_SMCR_ITR1 (1 << GTIM_SMCR_TS_SHIFT) /* 001: Internal Trigger 1 (ITR1). TIM2 */
+# define GTIM_SMCR_ITR2 (2 << GTIM_SMCR_TS_SHIFT) /* 010: Internal Trigger 2 (ITR2). TIM3 */
+# define GTIM_SMCR_ITR3 (3 << GTIM_SMCR_TS_SHIFT) /* 011: Internal Trigger 3 (ITR3). TIM4 */
+# define GTIM_SMCR_TI1FED (4 << GTIM_SMCR_TS_SHIFT) /* 100: TI1 Edge Detector (TI1F_ED) */
+# define GTIM_SMCR_TI1FP1 (5 << GTIM_SMCR_TS_SHIFT) /* 101: Filtered Timer Input 1 (TI1FP1) */
+# define GTIM_SMCR_TI2FP2 (6 << GTIM_SMCR_TS_SHIFT) /* 110: Filtered Timer Input 2 (TI2FP2) */
+# define GTIM_SMCR_ETRF (7 << GTIM_SMCR_TS_SHIFT) /* 111: External Trigger input (ETRF) */
+#define GTIM_SMCR_MSM (1 << 7) /* Bit 7: Master/Slave mode */
+#define GTIM_SMCR_ETF_SHIFT (8) /* Bits 11-8: External Trigger Filter */
+#define GTIM_SMCR_ETF_MASK (0x0f << GTIM_SMCR_ETF_SHIFT)
+# define GTIM_SMCR_NOFILT (0 << GTIM_SMCR_ETF_SHIFT) /* 0000: No filter, sampling is done at fDTS */
+# define GTIM_SMCR_FCKINT2 (1 << GTIM_SMCR_ETF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */
+# define GTIM_SMCR_FCKINT4 (2 << GTIM_SMCR_ETF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */
+# define GTIM_SMCR_FCKINT8 (3 << GTIM_SMCR_ETF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */
+# define GTIM_SMCR_FDTSd26 (4 << GTIM_SMCR_ETF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */
+# define GTIM_SMCR_FDTSd28 (5 << GTIM_SMCR_ETF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */
+# define GTIM_SMCR_FDTSd36 (6 << GTIM_SMCR_ETF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */
+# define GTIM_SMCR_FDTSd38 (7 << GTIM_SMCR_ETF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */
+# define GTIM_SMCR_FDTSd86 (8 << GTIM_SMCR_ETF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */
+# define GTIM_SMCR_FDTSd88 (9 << GTIM_SMCR_ETF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */
+# define GTIM_SMCR_FDTSd165 (10 << GTIM_SMCR_ETF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */
+# define GTIM_SMCR_FDTSd166 (11 << GTIM_SMCR_ETF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */
+# define GTIM_SMCR_FDTSd168 (12 << GTIM_SMCR_ETF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */
+# define GTIM_SMCR_FDTSd325 (13 << GTIM_SMCR_ETF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */
+# define GTIM_SMCR_FDTSd326 (14 << GTIM_SMCR_ETF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */
+# define GTIM_SMCR_FDTSd328 (15 << GTIM_SMCR_ETF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */
+#define GTIM_SMCR_ETPS_SHIFT (12) /* Bits 13-12: External Trigger Prescaler */
+#define GTIM_SMCR_ETPS_MASK (3 << GTIM_SMCR_ETPS_SHIFT)
+# define GTIM_SMCR_PSCOFF (0 << GTIM_SMCR_ETPS_SHIFT) /* 00: Prescaler OFF */
+# define GTIM_SMCR_ETRPd2 (1 << GTIM_SMCR_ETPS_SHIFT) /* 01: ETRP frequency divided by 2 */
+# define GTIM_SMCR_ETRPd4 (2 << GTIM_SMCR_ETPS_SHIFT) /* 10: ETRP frequency divided by 4 */
+# define GTIM_SMCR_ETRPd8 (3 << GTIM_SMCR_ETPS_SHIFT) /* 11: ETRP frequency divided by 8 */
+#define GTIM_SMCR_ECE (1 << 14) /* Bit 14: External Clock enable */
+#define GTIM_SMCR_ETP (1 << 15) /* Bit 15: External Trigger Polarity */
+
+/* DMA/Interrupt enable register (TIM2-5 and TIM9-14) */
+
+#define GTIM_DIER_UIE (1 << 0) /* Bit 0: Update interrupt enable */
+#define GTIM_DIER_CC1IE (1 << 1) /* Bit 1: Capture/Compare 1 interrupt enable */
+#define GTIM_DIER_CC2IE (1 << 2) /* Bit 2: Capture/Compare 2 interrupt enable (TIM2-5,9,&12 only) */
+#define GTIM_DIER_CC3IE (1 << 3) /* Bit 3: Capture/Compare 3 interrupt enable (TIM2-5 only) */
+#define GTIM_DIER_CC4IE (1 << 4) /* Bit 4: Capture/Compare 4 interrupt enable (TIM2-5 only) */
+#define GTIM_DIER_TIE (1 << 6) /* Bit 6: Trigger interrupt enable (TIM2-5,9,&12 only) */
+#define GTIM_DIER_UDE (1 << 8) /* Bit 8: Update DMA request enable (TIM2-5 only) */
+#define GTIM_DIER_CC1DE (1 << 9) /* Bit 9: Capture/Compare 1 DMA request enable (TIM2-5 only) */
+#define GTIM_DIER_CC2DE (1 << 10) /* Bit 10: Capture/Compare 2 DMA request enable (TIM2-5 only) */
+#define GTIM_DIER_CC3DE (1 << 11) /* Bit 11: Capture/Compare 3 DMA request enable (TIM2-5 only) */
+#define GTIM_DIER_CC4DE (1 << 12) /* Bit 12: Capture/Compare 4 DMA request enable (TIM2-5 only) */
+#define GTIM_DIER_TDE (1 << 14) /* Bit 14: Trigger DMA request enable (TIM2-5 only) */
+
+/* Status register */
+
+#define GTIM_SR_UIF (1 << 0) /* Bit 0: Update interrupt flag */
+#define GTIM_SR_CC1IF (1 << 1) /* Bit 1: Capture/compare 1 interrupt Flag */
+#define GTIM_SR_CC2IF (1 << 2) /* Bit 2: Capture/Compare 2 interrupt Flag (TIM2-5,9,&12 only) */
+#define GTIM_SR_CC3IF (1 << 3) /* Bit 3: Capture/Compare 3 interrupt Flag (TIM2-5 only) */
+#define GTIM_SR_CC4IF (1 << 4) /* Bit 4: Capture/Compare 4 interrupt Flag (TIM2-5 only) */
+#define GTIM_SR_TIF (1 << 6) /* Bit 6: Trigger interrupt Flag (TIM2-5,9,&12 only) */
+#define GTIM_SR_CC1OF (1 << 9) /* Bit 9: Capture/Compare 1 Overcapture Flag */
+#define GTIM_SR_CC2OF (1 << 10) /* Bit 10: Capture/Compare 2 Overcapture Flag (TIM2-5,9,&12 only) */
+#define GTIM_SR_CC3OF (1 << 11) /* Bit 11: Capture/Compare 3 Overcapture Flag (TIM2-5 only) */
+#define GTIM_SR_CC4OF (1 << 12) /* Bit 12: Capture/Compare 4 Overcapture Flag (TIM2-5 only) */
+
+/* Event generation register (TIM2-5 and TIM9-14) */
+
+#define GTIM_EGR_UG (1 << 0) /* Bit 0: Update generation */
+#define GTIM_EGR_CC1G (1 << 1) /* Bit 1: Capture/compare 1 generation */
+#define GTIM_EGR_CC2G (1 << 2) /* Bit 2: Capture/compare 2 generation (TIM2-5,9,&12 only) */
+#define GTIM_EGR_CC3G (1 << 3) /* Bit 3: Capture/compare 3 generation (TIM2-5 only) */
+#define GTIM_EGR_CC4G (1 << 4) /* Bit 4: Capture/compare 4 generation (TIM2-5 only) */
+#define GTIM_EGR_TG (1 << 6) /* Bit 6: Trigger generation (TIM2-5,9,&12 only) */
+
+/* Capture/compare mode register 1 - Output compare mode (TIM2-5 and TIM9-14) */
+
+#define GTIM_CCMR1_CC1S_SHIFT (0) /* Bits 1-0: Capture/Compare 1 Selection */
+#define GTIM_CCMR1_CC1S_MASK (3 << GTIM_CCMR1_CC1S_SHIFT)
+ /* (See common CCMR Capture/Compare Selection definitions below) */
+#define GTIM_CCMR1_OC1FE (1 << 2) /* Bit 2: Output Compare 1 Fast enable */
+#define GTIM_CCMR1_OC1PE (1 << 3) /* Bit 3: Output Compare 1 Preload enable */
+#define GTIM_CCMR1_OC1M_SHIFT (4) /* Bits 6-4: Output Compare 1 Mode */
+#define GTIM_CCMR1_OC1M_MASK (7 << GTIM_CCMR1_OC1M_SHIFT)
+ /* (See common CCMR Output Compare Mode definitions below) */
+#define GTIM_CCMR1_OC1CE (1 << 7) /* Bit 7: Output Compare 1Clear Enable */
+#define GTIM_CCMR1_CC2S_SHIFT (8) /* Bits 9-8: Capture/Compare 2 Selection */
+#define GTIM_CCMR1_CC2S_MASK (3 << GTIM_CCMR1_CC2S_SHIFT)
+ /* (See common CCMR Capture/Compare Selection definitions below) */
+#define GTIM_CCMR1_OC2FE (1 << 10) /* Bit 10: Output Compare 2 Fast enable */
+#define GTIM_CCMR1_OC2PE (1 << 11) /* Bit 11: Output Compare 2 Preload enable */
+#define GTIM_CCMR1_OC2M_SHIFT (12) /* Bits 14-12: Output Compare 2 Mode */
+#define GTIM_CCMR1_OC2M_MASK (7 << GTIM_CCMR1_OC2M_SHIFT)
+ /* (See common CCMR Output Compare Mode definitions below) */
+#define GTIM_CCMR1_OC2CE (1 << 15) /* Bit 15: Output Compare 2 Clear Enable */
+
+/* Common CCMR (unshifted) Capture/Compare Selection bit-field definitions */
+
+#define GTIM_CCMR_CCS_CCOUT (0) /* 00: CCx channel output */
+#define GTIM_CCMR_CCS_CCIN1 (1) /* 01: CCx channel input, ICx is TIx */
+#define GTIM_CCMR_CCS_CCIN2 (2) /* 10: CCx channel input, ICx is TIy */
+#define GTIM_CCMR_CCS_CCINTRC (3) /* 11: CCx channel input, ICx is TRC */
+
+/* Common CCMR (unshifted) Compare Mode bit field definitions */
+
+#define GTIM_CCMR_MODE_FRZN (0) /* 000: Frozen */
+#define GTIM_CCMR_MODE_CHACT (1) /* 001: Channel x active on match */
+#define GTIM_CCMR_MODE_CHINACT (2) /* 010: Channel x inactive on match */
+#define GTIM_CCMR_MODE_OCREFTOG (3) /* 011: OCxREF toggle ATIM_CNT=ATIM_CCRx */
+#define GTIM_CCMR_MODE_OCREFLO (4) /* 100: OCxREF forced low */
+#define GTIM_CCMR_MODE_OCREFHI (5) /* 101: OCxREF forced high */
+#define GTIM_CCMR_MODE_PWM1 (6) /* 110: PWM mode 1 */
+#define GTIM_CCMR_MODE_PWM2 (7) /* 111: PWM mode 2 */
+
+/* Capture/compare mode register 1 - Input capture mode (TIM2-5 and TIM9-14) */
+
+ /* Bits 1-0 (Same as Output Compare Mode) */
+#define GTIM_CCMR1_IC1PSC_SHIFT (2) /* Bits 3-2: Input Capture 1 Prescaler */
+#define GTIM_CCMR1_IC1PSC_MASK (3 << GTIM_CCMR1_IC1PSC_SHIFT)
+ /* (See common CCMR Input Capture Prescaler definitions below) */
+#define GTIM_CCMR1_IC1F_SHIFT (4) /* Bits 7-4: Input Capture 1 Filter */
+#define GTIM_CCMR1_IC1F_MASK (0x0f << GTIM_CCMR1_IC1F_SHIFT)
+ /* (See common CCMR Input Capture Filter definitions below) */
+ /* Bits 9-8: (Same as Output Compare Mode) */
+#define GTIM_CCMR1_IC2PSC_SHIFT (10) /* Bits 11-10: Input Capture 2 Prescaler */
+#define GTIM_CCMR1_IC2PSC_MASK (3 << GTIM_CCMR1_IC2PSC_SHIFT)
+ /* (See common CCMR Input Capture Prescaler definitions below) */
+#define GTIM_CCMR1_IC2F_SHIFT (12) /* Bits 15-12: Input Capture 2 Filter */
+#define GTIM_CCMR1_IC2F_MASK (0x0f << GTIM_CCMR1_IC2F_SHIFT)
+ /* (See common CCMR Input Capture Filter definitions below) */
+
+/* Common CCMR (unshifted) Input Capture Prescaler bit-field definitions */
+
+#define GTIM_CCMR_ICPSC_NOPSC (0) /* 00: no prescaler, capture each edge */
+#define GTIM_CCMR_ICPSC_EVENTS2 (1) /* 01: capture once every 2 events */
+#define GTIM_CCMR_ICPSC_EVENTS4 (2) /* 10: capture once every 4 events */
+#define GTIM_CCMR_ICPSC_EVENTS8 (3) /* 11: capture once every 8 events */
+
+/* Common CCMR (unshifted) Input Capture Filter bit-field definitions */
+
+#define GTIM_CCMR_ICF_NOFILT (0) /* 0000: No filter, sampling at fDTS */
+#define GTIM_CCMR_ICF_FCKINT2 (1) /* 0001: fSAMPLING=fCK_INT, N=2 */
+#define GTIM_CCMR_ICF_FCKINT4 (2) /* 0010: fSAMPLING=fCK_INT, N=4 */
+#define GTIM_CCMR_ICF_FCKINT8 (3) /* 0011: fSAMPLING=fCK_INT, N=8 */
+#define GTIM_CCMR_ICF_FDTSd26 (4) /* 0100: fSAMPLING=fDTS/2, N=6 */
+#define GTIM_CCMR_ICF_FDTSd28 (5) /* 0101: fSAMPLING=fDTS/2, N=8 */
+#define GTIM_CCMR_ICF_FDTSd46 (6) /* 0110: fSAMPLING=fDTS/4, N=6 */
+#define GTIM_CCMR_ICF_FDTSd48 (7) /* 0111: fSAMPLING=fDTS/4, N=8 */
+#define GTIM_CCMR_ICF_FDTSd86 (8) /* 1000: fSAMPLING=fDTS/8, N=6 */
+#define GTIM_CCMR_ICF_FDTSd88 (9) /* 1001: fSAMPLING=fDTS/8, N=8 */
+#define GTIM_CCMR_ICF_FDTSd165 (10) /* 1010: fSAMPLING=fDTS/16, N=5 */
+#define GTIM_CCMR_ICF_FDTSd166 (11) /* 1011: fSAMPLING=fDTS/16, N=6 */
+#define GTIM_CCMR_ICF_FDTSd168 (12) /* 1100: fSAMPLING=fDTS/16, N=8 */
+#define GTIM_CCMR_ICF_FDTSd325 (13) /* 1101: fSAMPLING=fDTS/32, N=5 */
+#define GTIM_CCMR_ICF_FDTSd326 (14) /* 1110: fSAMPLING=fDTS/32, N=6 */
+#define GTIM_CCMR_ICF_FDTSd328 (15) /* 1111: fSAMPLING=fDTS/32, N=8 */
+
+/* Capture/compare mode register 2 - Output Compare mode (TIM2-5 only) */
+
+#define GTIM_CCMR2_CC3S_SHIFT (0) /* Bits 1-0: Capture/Compare 3 Selection */
+#define GTIM_CCMR2_CC3S_MASK (3 << GTIM_CCMR2_CC3S_SHIFT)
+ /* (See common CCMR Capture/Compare Selection definitions above) */
+#define GTIM_CCMR2_OC3FE (1 << 2) /* Bit 2: Output Compare 3 Fast enable */
+#define GTIM_CCMR2_OC3PE (1 << 3) /* Bit 3: Output Compare 3 Preload enable */
+#define GTIM_CCMR2_OC3M_SHIFT (4) /* Bits 6-4: Output Compare 3 Mode */
+#define GTIM_CCMR2_OC3M_MASK (7 << GTIM_CCMR2_OC3M_SHIFT)
+ /* (See common CCMR Output Compare Mode definitions above) */
+#define GTIM_CCMR2_OC3CE (1 << 7) /* Bit 7: Output Compare 3 Clear Enable */
+#define GTIM_CCMR2_CC4S_SHIFT (8) /* Bits 9-8: Capture/Compare 4 Selection */
+#define GTIM_CCMR2_CC4S_MASK (3 << GTIM_CCMR2_CC4S_SHIFT)
+ /* (See common CCMR Capture/Compare Selection definitions above) */
+#define GTIM_CCMR2_OC4FE (1 << 10) /* Bit 10: Output Compare 4 Fast enable */
+#define GTIM_CCMR2_OC4PE (1 << 11) /* Bit 11: Output Compare 4 Preload enable */
+#define GTIM_CCMR2_OC4M_SHIFT (12) /* Bits 14-12: Output Compare 4 Mode */
+#define GTIM_CCMR2_OC4M_MASK (7 << GTIM_CCMR2_OC4M_SHIFT)
+ /* (See common CCMR Output Compare Mode definitions above) */
+#define GTIM_CCMR2_OC4CE (1 << 15) /* Bit 15: Output Compare 4 Clear Enable */
+
+/* Capture/compare mode register 2 - Input capture mode (TIM2-5 only) */
+
+ /* Bits 1-0 (Same as Output Compare Mode) */
+#define GTIM_CCMR2_IC3PSC_SHIFT (2) /* Bits 3-2: Input Capture 3 Prescaler */
+#define GTIM_CCMR2_IC3PSC_MASK (3 << GTIM_CCMR2_IC3PSC_SHIFT)
+ /* (See common CCMR Input Capture Prescaler definitions below) */
+#define GTIM_CCMR2_IC3F_SHIFT (4) /* Bits 7-4: Input Capture 3 Filter */
+#define GTIM_CCMR2_IC3F_MASK (0x0f << GTIM_CCMR2_IC3F_SHIFT)
+ /* (See common CCMR Input Capture Filter definitions below) */
+ /* Bits 9-8: (Same as Output Compare Mode) */
+#define GTIM_CCMR2_IC4PSC_SHIFT (10) /* Bits 11-10: Input Capture 4 Prescaler */
+#define GTIM_CCMR2_IC4PSC_MASK (3 << GTIM_CCMR2_IC4PSC_SHIFT)
+ /* (See common CCMR Input Capture Prescaler definitions below) */
+#define GTIM_CCMR2_IC4F_SHIFT (12) /* Bits 15-12: Input Capture 4 Filter */
+#define GTIM_CCMR2_IC4F_MASK (0x0f << GTIM_CCMR2_IC4F_SHIFT)
+ /* (See common CCMR Input Capture Filter definitions below) */
+
+/* Capture/compare enable register (TIM2-5 and TIM9-14) */
+
+#define GTIM_CCER_CC1E (1 << 0) /* Bit 0: Capture/Compare 1 output enable */
+#define GTIM_CCER_CC1P (1 << 1) /* Bit 1: Capture/Compare 1 output Polarity */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define GTIM_CCER_CC1NP (1 << 3) /* Bit 3: Capture/Compare 1 output Polarity */
+#endif
+
+#define GTIM_CCER_CC2E (1 << 4) /* Bit 4: Capture/Compare 2 output enable (TIM2-5,9&12 only) */
+#define GTIM_CCER_CC2P (1 << 5) /* Bit 5: Capture/Compare 2 output Polarity (TIM2-5,9&12 only) */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define GTIM_CCER_CC2NP (1 << 7) /* Bit 7: Capture/Compare 2 output Polarity (TIM2-5,9&12 only) */
+#endif
+
+#define GTIM_CCER_CC3E (1 << 8) /* Bit 8: Capture/Compare 3 output enable (TIM2-5 only) */
+#define GTIM_CCER_CC3P (1 << 9) /* Bit 9: Capture/Compare 3 output Polarity (TIM2-5 only) */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define GTIM_CCER_CC3NP (1 << 11) /* Bit 11: Capture/Compare 3 output Polarity (TIM2-5 only) */
+#endif
+
+#define GTIM_CCER_CC4E (1 << 12) /* Bit 12: Capture/Compare 4 output enable (TIM2-5 only) */
+#define GTIM_CCER_CC4P (1 << 13) /* Bit 13: Capture/Compare 4 output Polarity (TIM2-5 only) */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define GTIM_CCER_CC4NP (1 << 15) /* Bit 15: Capture/Compare 4 output Polarity (TIM2-5 only) */
+#endif
+
+/* DMA control register */
+
+#define GTIM_DCR_DBL_SHIFT (8) /* Bits 12-8: DMA Burst Length */
+#define GTIM_DCR_DBL_MASK (0x1f << GTIM_DCR_DBL_SHIFT)
+#define GTIM_DCR_DBA_SHIFT (0) /* Bits 4-0: DMA Base Address */
+#define GTIM_DCR_DBA_MASK (0x1f << GTIM_DCR_DBA_SHIFT)
+
+/* Timer 2/5 option register */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define TIM2_OR_ITR1_RMP_SHIFT (10) /* Bits 10-11: Internal trigger 1 remap */
+# define TIM2_OR_ITR1_RMP_MASK (3 << TIM2_OR_ITR1_RMP_SHIFT)
+# define TIM2_OR_ITR1_TIM8_TRGOUT (0 << TIM2_OR_ITR1_RMP_SHIFT) /* 00: TIM2_ITR1 input connected to TIM8_TRGOUT */
+# define TIM2_OR_ITR1_PTP (1 << TIM2_OR_ITR1_RMP_SHIFT) /* 01: TIM2_ITR1 input connected to PTP trigger output */
+# define TIM2_OR_ITR1_OTGFSSOF (2 << TIM2_OR_ITR1_RMP_SHIFT) /* 10: TIM2_ITR1 input connected to OTG FS SOF */
+# define TIM2_OR_ITR1_OTGHSSOF (3 << TIM2_OR_ITR1_RMP_SHIFT) /* 11: TIM2_ITR1 input connected to OTG HS SOF */
+
+# define TIM5_OR_TI4_RMP_SHIFT (6) /* Bits 6-7: Internal trigger 4 remap */
+# define TIM5_OR_TI4_RMP_MASK (3 << TIM5_OR_TI4_RMP_SHIFT)
+# define TIM5_OR_TI4_GPIO (0 << TIM5_OR_TI4_RMP_SHIFT) /* 00: TIM5_CH4 input connected to GPIO */
+# define TIM5_OR_TI4_LSI (1 << TIM5_OR_TI4_RMP_SHIFT) /* 01: TIM5_CH4 input connected to LSI internal clock */
+# define TIM5_OR_TI4_LSE (2 << TIM5_OR_TI4_RMP_SHIFT) /* 10: TIM5_CH4 input connected to LSE internal clock */
+# define TIM5_OR_TI4_RTC (3 << TIM5_OR_TI4_RMP_SHIFT) /* 11: TIM5_CH4 input connected to RTC output event */
+
+# define TIM11_OR_TI1_RMP_SHIFT (6) /* Bits 6-7: Internal trigger 4 remap */
+# define TIM11_OR_TI1_RMP_MASK (3 << TIM11_OR_TI1_RMP_SHIFT)
+# define TIM11_OR_TI1_GPIO (0 << TIM11_OR_TI1_RMP_SHIFT) /* 00-11: TIM11_CH1 input connected to GPIO */
+# define TIM11_OR_TI1_HSERTC (3 << TIM11_OR_TI1_RMP_SHIFT) /* 11: TIM11_CH1 input connected to HSE_RTC clock */
+#endif
+
+/* Control register 1 */
+
+#define BTIM_CR1_CEN (1 << 0) /* Bit 0: Counter enable */
+#define BTIM_CR1_UDIS (1 << 1) /* Bit 1: Update Disable */
+#define BTIM_CR1_URS (1 << 2) /* Bit 2: Update Request Source */
+#define BTIM_CR1_OPM (1 << 3) /* Bit 3: One Pulse Mode */
+#define BTIM_CR1_ARPE (1 << 7) /* Bit 7: Auto-Reload Preload enable */
+
+/* Control register 2 */
+
+#define BTIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection */
+#define BTIM_CR2_MMS_MASK (7 << BTIM_CR2_MMS_SHIFT)
+# define BTIM_CR2_RESET (0 << BTIM_CR2_MMS_SHIFT) /* 000: Reset */
+# define BTIM_CR2_ENAB (1 << BTIM_CR2_MMS_SHIFT) /* 001: Enable */
+# define BTIM_CR2_UPDT (2 << BTIM_CR2_MMS_SHIFT) /* 010: Update */
+
+/* DMA/Interrupt enable register */
+
+#define BTIM_DIER_UIE (1 << 0) /* Bit 0: Update interrupt enable */
+#define BTIM_DIER_UDE (1 << 8) /* Bit 8: Update DMA request enable */
+
+/* Status register */
+
+#define BTIM_SR_UIF (1 << 0) /* Bit 0: Update interrupt flag */
+
+/* Event generation register */
+
+#define BTIM_EGR_UG (1 << 0) /* Bit 0: Update generation */
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_TIM_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_uart.h b/nuttx/arch/arm/src/stm32/chip/stm32_uart.h
new file mode 100644
index 000000000..d3c1e137e
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_uart.h
@@ -0,0 +1,229 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_uart.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STC_STM32_CHIP_STM32_UART_H
+#define __ARCH_ARM_STC_STM32_CHIP_STM32_UART_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_USART_SR_OFFSET 0x0000 /* Status register (32-bits) */
+#define STM32_USART_DR_OFFSET 0x0004 /* Data register (32-bits) */
+#define STM32_USART_BRR_OFFSET 0x0008 /* Baud Rate Register (32-bits) */
+#define STM32_USART_CR1_OFFSET 0x000c /* Control register 1 (32-bits) */
+#define STM32_USART_CR2_OFFSET 0x0010 /* Control register 2 (32-bits) */
+#define STM32_USART_CR3_OFFSET 0x0014 /* Control register 3 (32-bits) */
+#define STM32_USART_GTPR_OFFSET 0x0018 /* Guard time and prescaler register (32-bits) */
+
+/* Register Addresses ***************************************************************/
+
+#if STM32_NUSART > 0
+# define STM32_USART1_SR (STM32_USART1_BASE+STM32_USART_SR_OFFSET)
+# define STM32_USART1_DR (STM32_USART1_BASE+STM32_USART_DR_OFFSET)
+# define STM32_USART1_BRR (STM32_USART1_BASE+STM32_USART_BRR_OFFSET)
+# define STM32_USART1_CR1 (STM32_USART1_BASE+STM32_USART_CR1_OFFSET)
+# define STM32_USART1_CR2 (STM32_USART1_BASE+STM32_USART_CR2_OFFSET)
+# define STM32_USART1_CR3 (STM32_USART1_BASE+STM32_USART_CR3_OFFSET)
+# define STM32_USART1_GTPR (STM32_USART1_BASE+STM32_USART_GTPR_OFFSET)
+#endif
+
+#if STM32_NUSART > 1
+# define STM32_USART2_SR (STM32_USART2_BASE+STM32_USART_SR_OFFSET)
+# define STM32_USART2_DR (STM32_USART2_BASE+STM32_USART_DR_OFFSET)
+# define STM32_USART2_BRR (STM32_USART2_BASE+STM32_USART_BRR_OFFSET)
+# define STM32_USART2_CR1 (STM32_USART2_BASE+STM32_USART_CR1_OFFSET)
+# define STM32_USART2_CR2 (STM32_USART2_BASE+STM32_USART_CR2_OFFSET)
+# define STM32_USART2_CR3 (STM32_USART2_BASE+STM32_USART_CR3_OFFSET)
+# define STM32_USART2_GTPR (STM32_USART2_BASE+STM32_USART_GTPR_OFFSET)
+#endif
+
+#if STM32_NUSART > 2
+# define STM32_USART3_SR (STM32_USART3_BASE+STM32_USART_SR_OFFSET)
+# define STM32_USART3_DR (STM32_USART3_BASE+STM32_USART_DR_OFFSET)
+# define STM32_USART3_BRR (STM32_USART3_BASE+STM32_USART_BRR_OFFSET)
+# define STM32_USART3_CR1 (STM32_USART3_BASE+STM32_USART_CR1_OFFSET)
+# define STM32_USART3_CR2 (STM32_USART3_BASE+STM32_USART_CR2_OFFSET)
+# define STM32_USART3_CR3 (STM32_USART3_BASE+STM32_USART_CR3_OFFSET)
+# define STM32_USART3_GTPR (STM32_USART3_BASE+STM32_USART_GTPR_OFFSET)
+#endif
+
+#if STM32_NUSART > 3
+# define STM32_UART4_SR (STM32_UART4_BASE+STM32_USART_SR_OFFSET)
+# define STM32_UART4_DR (STM32_UART4_BASE+STM32_USART_DR_OFFSET)
+# define STM32_UART4_BRR (STM32_UART4_BASE+STM32_USART_BRR_OFFSET)
+# define STM32_UART4_CR1 (STM32_UART4_BASE+STM32_USART_CR1_OFFSET)
+# define STM32_UART4_CR2 (STM32_UART4_BASE+STM32_USART_CR2_OFFSET)
+# define STM32_UART4_CR3 (STM32_UART4_BASE+STM32_USART_CR3_OFFSET)
+#endif
+
+#if STM32_NUSART > 4
+# define STM32_UART5_SR (STM32_UART5_BASE+STM32_USART_SR_OFFSET)
+# define STM32_UART5_DR (STM32_UART5_BASE+STM32_USART_DR_OFFSET)
+# define STM32_UART5_BRR (STM32_UART5_BASE+STM32_USART_BRR_OFFSET)
+# define STM32_UART5_CR1 (STM32_UART5_BASE+STM32_USART_CR1_OFFSET)
+# define STM32_UART5_CR2 (STM32_UART5_BASE+STM32_USART_CR2_OFFSET)
+# define STM32_UART5_CR3 (STM32_UART5_BASE+STM32_USART_CR3_OFFSET)
+#endif
+
+#if STM32_NUSART > 5
+# define STM32_USART6_SR (STM32_USART6_BASE+STM32_USART_SR_OFFSET)
+# define STM32_USART6_DR (STM32_USART6_BASE+STM32_USART_DR_OFFSET)
+# define STM32_USART6_BRR (STM32_USART6_BASE+STM32_USART_BRR_OFFSET)
+# define STM32_USART6_CR1 (STM32_USART6_BASE+STM32_USART_CR1_OFFSET)
+# define STM32_USART6_CR2 (STM32_USART6_BASE+STM32_USART_CR2_OFFSET)
+# define STM32_USART6_CR3 (STM32_USART6_BASE+STM32_USART_CR3_OFFSET)
+# define STM32_USART6_GTPR (STM32_USART6_BASE+STM32_USART_GTPR_OFFSET)
+#endif
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* Status register */
+
+#define USART_SR_PE (1 << 0) /* Bit 0: Parity Error */
+#define USART_SR_FE (1 << 1) /* Bit 1: Framing Error */
+#define USART_SR_NE (1 << 2) /* Bit 2: Noise Error Flag */
+#define USART_SR_ORE (1 << 3) /* Bit 3: OverRun Error */
+#define USART_SR_IDLE (1 << 4) /* Bit 4: IDLE line detected */
+#define USART_SR_RXNE (1 << 5) /* Bit 5: Read Data Register Not Empty */
+#define USART_SR_TC (1 << 6) /* Bit 6: Transmission Complete */
+#define USART_SR_TXE (1 << 7) /* Bit 7: Transmit Data Register Empty */
+#define USART_SR_LBD (1 << 8) /* Bit 8: LIN Break Detection Flag */
+#define USART_SR_CTS (1 << 9) /* Bit 9: CTS Flag */
+
+#define USART_SR_ALLBITS (0x03ff)
+#define USART_SR_CLRBITS (USART_SR_CTS|USART_SR_LBD) /* Cleared by SW write to SR */
+
+/* Data register */
+
+#define USART_DR_SHIFT (0) /* Bits 8:0: Data value */
+#define USART_DR_MASK (0xff << USART_DR_SHIFT)
+
+/* Baud Rate Register */
+
+#define USART_BRR_FRAC_SHIFT (0) /* Bits 3-0: fraction of USARTDIV */
+#define USART_BRR_FRAC_MASK (0x0f << USART_BRR_FRAC_SHIFT)
+#define USART_BRR_MANT_SHIFT (4) /* Bits 15-4: mantissa of USARTDIV */
+#define USART_BRR_MANT_MASK (0x0fff << USART_BRR_MANT_SHIFT)
+
+/* Control register 1 */
+
+#define USART_CR1_SBK (1 << 0) /* Bit 0: Send Break */
+#define USART_CR1_RWU (1 << 1) /* Bit 1: Receiver wakeup */
+#define USART_CR1_RE (1 << 2) /* Bit 2: Receiver Enable */
+#define USART_CR1_TE (1 << 3) /* Bit 3: Transmitter Enable */
+#define USART_CR1_IDLEIE (1 << 4) /* Bit 4: IDLE Interrupt Enable */
+#define USART_CR1_RXNEIE (1 << 5) /* Bit 5: RXNE Interrupt Enable */
+#define USART_CR1_TCIE (1 << 6) /* Bit 6: Transmission Complete Interrupt Enable */
+#define USART_CR1_TXEIE (1 << 7) /* Bit 7: TXE Interrupt Enable */
+#define USART_CR1_PEIE (1 << 8) /* Bit 8: PE Interrupt Enable */
+#define USART_CR1_PS (1 << 9) /* Bit 9: Parity Selection */
+#define USART_CR1_PCE (1 << 10) /* Bit 10: Parity Control Enable */
+#define USART_CR1_WAKE (1 << 11) /* Bit 11: Wakeup method */
+#define USART_CR1_M (1 << 12) /* Bit 12: word length */
+#define USART_CR1_UE (1 << 13) /* Bit 13: USART Enable */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define USART_CR1_OVER8 (1 << 15) /* Bit 15: Oversampling mode */
+#endif
+
+#define USART_CR1_ALLINTS (USART_CR1_IDLEIE|USART_CR1_RXNEIE|USART_CR1_TCIE|USART_CR1_PEIE)
+
+/* Control register 2 */
+
+#define USART_CR2_ADD_SHIFT (0) /* Bits 3-0: Address of the USART node */
+#define USART_CR2_ADD_MASK (0x0f << USART_CR2_ADD_SHIFT)
+#define USART_CR2_LBDL (1 << 5) /* Bit 5: LIN Break Detection Length */
+#define USART_CR2_LBDIE (1 << 6) /* Bit 6: LIN Break Detection Interrupt Enable */
+#define USART_CR2_LBCL (1 << 8) /* Bit 8: Last Bit Clock pulse */
+#define USART_CR2_CPHA (1 << 9) /* Bit 9: Clock Phase */
+#define USART_CR2_CPOL (1 << 10) /* Bit 10: Clock Polarity */
+#define USART_CR2_CLKEN (1 << 11) /* Bit 11: Clock Enable */
+#define USART_CR2_STOP_SHIFT (12) /* Bits 13-12: STOP bits */
+#define USART_CR2_STOP_MASK (3 << USART_CR2_STOP_SHIFT)
+# define USART_CR2_STOP1 (0 << USART_CR2_STOP_SHIFT) /* 00: 1 Stop bit */
+# define USART_CR2_STOP0p5 (1 << USART_CR2_STOP_SHIFT) /* 01: 0.5 Stop bit */
+# define USART_CR2_STOP2 (2 << USART_CR2_STOP_SHIFT) /* 10: 2 Stop bits */
+# define USART_CR2_STOP1p5 (3 << USART_CR2_STOP_SHIFT) /* 11: 1.5 Stop bit */
+#define USART_CR2_LINEN (1 << 14) /* Bit 14: LIN mode enable */
+
+/* Control register 3 */
+
+#define USART_CR3_EIE (1 << 0) /* Bit 0: Error Interrupt Enable */
+#define USART_CR3_IREN (1 << 1) /* Bit 1: IrDA mode Enable */
+#define USART_CR3_IRLP (1 << 2) /* Bit 2: IrDA Low-Power */
+#define USART_CR3_HDSEL (1 << 3) /* Bit 3: Half-Duplex Selection */
+#define USART_CR3_NACK (1 << 4) /* Bit 4: Smartcard NACK enable */
+#define USART_CR3_SCEN (1 << 5) /* Bit 5: Smartcard mode enable */
+#define USART_CR3_DMAR (1 << 6) /* Bit 6: DMA Enable Receiver */
+#define USART_CR3_DMAT (1 << 7) /* Bit 7: DMA Enable Transmitter */
+#define USART_CR3_RTSE (1 << 8) /* Bit 8: RTS Enable */
+#define USART_CR3_CTSE (1 << 9) /* Bit 9: CTS Enable */
+#define USART_CR3_CTSIE (1 << 10) /* Bit 10: CTS Interrupt Enable */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define USART_CR1_ONEBIT (1 << 11) /* Bit 11: One sample bit method enable */
+#endif
+
+/* Guard time and prescaler register */
+
+#define USART_GTPR_PSC_SHIFT (0) /* Bits 0-7: Prescaler value */
+#define USART_GTPR_PSC_MASK (0xff << USART_GTPR_PSC_SHIFT)
+#define USART_GTPR_GT_SHIFT (8) /* Bits 8-15: Guard time value */
+#define USART_GTPR_GT_MASK (0xff << USART_GTPR_GT_SHIFT)
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_STC_STM32_CHIP_STM32_UART_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_usbdev.h b/nuttx/arch/arm/src/stm32/chip/stm32_usbdev.h
new file mode 100644
index 000000000..daa9a926e
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_usbdev.h
@@ -0,0 +1,236 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_usbdev.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_CHIP_STM32_USBDEV_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_USBDEV_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <chip.h>
+
+#ifdef CONFIG_STM32_STM32F10XX
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+/* Endpoint Registers */
+
+#define STM32_USB_EPR_OFFSET(n) ((n) << 2) /* USB endpoint n register (16-bits) */
+#define STM32_USB_EP0R_OFFSET 0x0000 /* USB endpoint 0 register (16-bits) */
+#define STM32_USB_EP1R_OFFSET 0x0004 /* USB endpoint 1 register (16-bits) */
+#define STM32_USB_EP2R_OFFSET 0x0008 /* USB endpoint 2 register (16-bits) */
+#define STM32_USB_EP3R_OFFSET 0x000c /* USB endpoint 3 register (16-bits) */
+#define STM32_USB_EP4R_OFFSET 0x0010 /* USB endpoint 4 register (16-bits) */
+#define STM32_USB_EP5R_OFFSET 0x0014 /* USB endpoint 5 register (16-bits) */
+#define STM32_USB_EP6R_OFFSET 0x0018 /* USB endpoint 6 register (16-bits) */
+#define STM32_USB_EP7R_OFFSET 0x001c /* USB endpoint 7 register (16-bits) */
+
+/* Common Registers */
+
+#define STM32_USB_CNTR_OFFSET 0x0040 /* USB control register (16-bits) */
+#define STM32_USB_ISTR_OFFSET 0x0044 /* USB interrupt status register (16-bits) */
+#define STM32_USB_FNR_OFFSET 0x0048 /* USB frame number register (16-bits) */
+#define STM32_USB_DADDR_OFFSET 0x004c /* USB device address (16-bits) */
+#define STM32_USB_BTABLE_OFFSET 0x0050 /* Buffer table address (16-bits) */
+
+/* Buffer Descriptor Table (Relatative to BTABLE address) */
+
+#define STM32_USB_ADDR_TX_WOFFSET (0) /* Transmission buffer address n (16-bits) */
+#define STM32_USB_COUNT_TX_WOFFSET (2) /* Transmission byte count n (16-bits) */
+#define STM32_USB_ADDR_RX_WOFFSET (4) /* Reception buffer address n (16-bits) */
+#define STM32_USB_COUNT_RX_WOFFSET (6) /* Reception byte count n (16-bits) */
+
+#define STM32_USB_BTABLE_RADDR(ep,o) ((((uint32_t)getreg16(STM32_USB_BTABLE) + ((ep) << 3)) + (o)) << 1)
+#define STM32_USB_ADDR_TX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_ADDR_TX_WOFFSET)
+#define STM32_USB_COUNT_TX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_COUNT_TX_WOFFSET)
+#define STM32_USB_ADDR_RX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_ADDR_RX_WOFFSET)
+#define STM32_USB_COUNT_RX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_COUNT_RX_WOFFSET)
+
+/* Register Addresses ***************************************************************/
+
+/* Endpoint Registers */
+
+#define STM32_USB_EPR(n) (STM32_USB_BASE+STM32_USB_EPR_OFFSET(n))
+#define STM32_USB_EP0R (STM32_USB_BASE+STM32_USB_EP0R_OFFSET)
+#define STM32_USB_EP1R (STM32_USB_BASE+STM32_USB_EP1R_OFFSET)
+#define STM32_USB_EP2R (STM32_USB_BASE+STM32_USB_EP2R_OFFSET)
+#define STM32_USB_EP3R (STM32_USB_BASE+STM32_USB_EP3R_OFFSET)
+#define STM32_USB_EP4R (STM32_USB_BASE+STM32_USB_EP4R_OFFSET)
+#define STM32_USB_EP5R (STM32_USB_BASE+STM32_USB_EP5R_OFFSET)
+#define STM32_USB_EP6R (STM32_USB_BASE+STM32_USB_EP6R_OFFSET)
+#define STM32_USB_EP7R (STM32_USB_BASE+STM32_USB_EP7R_OFFSET)
+
+/* Common Registers */
+
+#define STM32_USB_CNTR (STM32_USB_BASE+STM32_USB_CNTR_OFFSET)
+#define STM32_USB_ISTR (STM32_USB_BASE+STM32_USB_ISTR_OFFSET)
+#define STM32_USB_FNR (STM32_USB_BASE+STM32_USB_FNR_OFFSET)
+#define STM32_USB_DADDR (STM32_USB_BASE+STM32_USB_DADDR_OFFSET)
+#define STM32_USB_BTABLE (STM32_USB_BASE+STM32_USB_BTABLE_OFFSET)
+
+/* Buffer Descriptor Table (Relatative to BTABLE address) */
+
+#define STM32_USB_BTABLE_ADDR(ep,o) (STM32_USBCANRAM_BASE+STM32_USB_BTABLE_RADDR(ep,o))
+#define STM32_USB_ADDR_TX(ep) STM32_USB_BTABLE_ADDR(ep,STM32_USB_ADDR_TX_WOFFSET)
+#define STM32_USB_COUNT_TX(ep) STM32_USB_BTABLE_ADDR(ep,STM32_USB_COUNT_TX_WOFFSET)
+#define STM32_USB_ADDR_RX(ep) STM32_USB_BTABLE_ADDR(ep,STM32_USB_ADDR_RX_WOFFSET)
+#define STM32_USB_COUNT_RX(ep) STM32_USB_BTABLE_ADDR(ep,STM32_USB_COUNT_RX_WOFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* USB endpoint register */
+
+#define USB_EPR_EA_SHIFT (0) /* Bits 3:0 [3:0]: Endpoint Address */
+#define USB_EPR_EA_MASK (0X0f << USB_EPR_EA_SHIFT)
+#define USB_EPR_STATTX_SHIFT (4) /* Bits 5-4: Status bits, for transmission transfers */
+#define USB_EPR_STATTX_MASK (3 << USB_EPR_STATTX_SHIFT)
+# define USB_EPR_STATTX_DIS (0 << USB_EPR_STATTX_SHIFT) /* EndPoint TX DISabled */
+# define USB_EPR_STATTX_STALL (1 << USB_EPR_STATTX_SHIFT) /* EndPoint TX STALLed */
+# define USB_EPR_STATTX_NAK (2 << USB_EPR_STATTX_SHIFT) /* EndPoint TX NAKed */
+# define USB_EPR_STATTX_VALID (3 << USB_EPR_STATTX_SHIFT) /* EndPoint TX VALID */
+# define USB_EPR_STATTX_DTOG1 (1 << USB_EPR_STATTX_SHIFT) /* EndPoint TX Data Toggle bit1 */
+# define USB_EPR_STATTX_DTOG2 (2 << USB_EPR_STATTX_SHIFT) /* EndPoint TX Data Toggle bit2 */
+#define USB_EPR_DTOG_TX (1 << 6) /* Bit 6: Data Toggle, for transmission transfers */
+#define USB_EPR_CTR_TX (1 << 7) /* Bit 7: Correct Transfer for transmission */
+#define USB_EPR_EP_KIND (1 << 8) /* Bit 8: Endpoint Kind */
+#define USB_EPR_EPTYPE_SHIFT (9) /* Bits 10-9: Endpoint type */
+#define USB_EPR_EPTYPE_MASK (3 << USB_EPR_EPTYPE_SHIFT)
+# define USB_EPR_EPTYPE_BULK (0 << USB_EPR_EPTYPE_SHIFT) /* EndPoint BULK */
+# define USB_EPR_EPTYPE_CONTROL (1 << USB_EPR_EPTYPE_SHIFT) /* EndPoint CONTROL */
+# define USB_EPR_EPTYPE_ISOC (2 << USB_EPR_EPTYPE_SHIFT) /* EndPoint ISOCHRONOUS */
+# define USB_EPR_EPTYPE_INTERRUPT (3 << USB_EPR_EPTYPE_SHIFT) /* EndPoint INTERRUPT */
+#define USB_EPR_SETUP (1 << 11) /* Bit 11: Setup transaction completed */
+#define USB_EPR_STATRX_SHIFT (12) /* Bits 13-12: Status bits, for reception transfers */
+#define USB_EPR_STATRX_MASK (3 << USB_EPR_STATRX_SHIFT)
+# define USB_EPR_STATRX_DIS (0 << USB_EPR_STATRX_SHIFT) /* EndPoint RX DISabled */
+# define USB_EPR_STATRX_STALL (1 << USB_EPR_STATRX_SHIFT) /* EndPoint RX STALLed */
+# define USB_EPR_STATRX_NAK (2 << USB_EPR_STATRX_SHIFT) /* EndPoint RX NAKed */
+# define USB_EPR_STATRX_VALID (3 << USB_EPR_STATRX_SHIFT) /* EndPoint RX VALID */
+# define USB_EPR_STATRX_DTOG1 (1 << USB_EPR_STATRX_SHIFT) /* EndPoint RX Data TOGgle bit1 */
+# define USB_EPR_STATRX_DTOG2 (2 << USB_EPR_STATRX_SHIFT) /* EndPoint RX Data TOGgle bit1 */
+#define USB_EPR_DTOG_RX (1 << 14) /* Bit 14: Data Toggle, for reception transfers */
+#define USB_EPR_CTR_RX (1 << 15) /* Bit 15: Correct Transfer for reception */
+
+/* USB control register */
+
+#define USB_CNTR_FRES (1 << 0) /* Bit 0: Force USB Reset */
+#define USB_CNTR_PDWN (1 << 1) /* Bit 1: Power down */
+#define USB_CNTR_LPMODE (1 << 2) /* Bit 2: Low-power mode */
+#define USB_CNTR_FSUSP (1 << 3) /* Bit 3: Force suspend */
+#define USB_CNTR_RESUME (1 << 4) /* Bit 4: Resume request */
+#define USB_CNTR_ESOFM (1 << 8) /* Bit 8: Expected Start Of Frame Interrupt Mask */
+#define USB_CNTR_SOFM (1 << 9) /* Bit 9: Start Of Frame Interrupt Mask */
+#define USB_CNTR_RESETM (1 << 10) /* Bit 10: USB Reset Interrupt Mask */
+#define USB_CNTR_SUSPM (1 << 11) /* Bit 11: Suspend mode Interrupt Mask */
+#define USB_CNTR_WKUPM (1 << 12) /* Bit 12: Wakeup Interrupt Mask */
+#define USB_CNTR_ERRM (1 << 13) /* Bit 13: Error Interrupt Mask */
+#define USB_CNTR_DMAOVRNM (1 << 14) /* Bit 14: Packet Memory Area Over / Underrun Interrupt Mask */
+#define USB_CNTR_CTRM (1 << 15) /* Bit 15: Correct Transfer Interrupt Mask */
+
+#define USB_CNTR_ALLINTS (USB_CNTR_ESOFM|USB_CNTR_SOFM|USB_CNTR_RESETM|USB_CNTR_SUSPM|\
+ USB_CNTR_WKUPM|USB_CNTR_ERRM|USB_CNTR_DMAOVRNM|USB_CNTR_CTRM)
+
+/* USB interrupt status register */
+
+#define USB_ISTR_EPID_SHIFT (0) /* Bits 3-0: Endpoint Identifier */
+#define USB_ISTR_EPID_MASK (0x0f << USB_ISTR_EPID_SHIFT)
+#define USB_ISTR_DIR (1 << 4) /* Bit 4: Direction of transaction */
+#define USB_ISTR_ESOF (1 << 8) /* Bit 8: Expected Start Of Frame */
+#define USB_ISTR_SOF (1 << 9) /* Bit 9: Start Of Frame */
+#define USB_ISTR_RESET (1 << 10) /* Bit 10: USB RESET request */
+#define USB_ISTR_SUSP (1 << 11) /* Bit 11: Suspend mode request */
+#define USB_ISTR_WKUP (1 << 12) /* Bit 12: Wake up */
+#define USB_ISTR_ERR (1 << 13) /* Bit 13: Error */
+#define USB_ISTR_DMAOVRN (1 << 14) /* Bit 14: Packet Memory Area Over / Underrun */
+#define USB_ISTR_CTR (1 << 15) /* Bit 15: Correct Transfer */
+
+#define USB_ISTR_ALLINTS (USB_ISTR_ESOF|USB_ISTR_SOF|USB_ISTR_RESET|USB_ISTR_SUSP|\
+ USB_ISTR_WKUP|USB_ISTR_ERR|USB_ISTR_DMAOVRN|USB_ISTR_CTR)
+
+/* USB frame number register */
+
+#define USB_FNR_FN_SHIFT (0) /* Bits 10-0: Frame Number */
+#define USB_FNR_FN_MASK (0x07ff << USB_FNR_FN_SHIFT)
+#define USB_FNR_LSOF_SHIFT (11) /* Bits 12-11: Lost SOF */
+#define USB_FNR_LSOF_MASK (3 << USB_FNR_LSOF_SHIFT)
+#define USB_FNR_LCK (1 << 13) /* Bit 13: Locked */
+#define USB_FNR_RXDM (1 << 14) /* Bit 14: Receive Data - Line Status */
+#define USB_FNR_RXDP (1 << 15) /* Bit 15: Receive Data + Line Status */
+
+/* USB device address */
+
+#define USB_DADDR_ADD_SHIFT (0) /* Bits 6-0: Device Address */
+#define USB_DADDR_ADD_MASK (0x7f << USB_DADDR_ADD_SHIFT)
+#define USB_DADDR_EF (1 << 7) /* Bit 7: Enable Function */
+
+/* Buffer table address */
+
+#define USB_BTABLE_SHIFT (3) /* Bits 15:3: Buffer Table */
+#define USB_BTABLE_MASK (0x1fff << USB_BTABLE_SHIFT)
+
+/* Transmission buffer address */
+
+#define USB_ADDR_TX_ZERO (1 << 0) /* Bit 0 Must always be written as ‘0’ */
+#define USB_ADDR_TX_SHIFT (1) /* Bits 15-1: Transmission Buffer Address */
+#define USB_ADDR_TX_MASK (0x7fff << USB_ADDR_ADDR_TX_SHIFT)
+
+/* Transmission byte count */
+
+#define USB_COUNT_TX_SHIFT (0) /* Bits 9-0: Transmission Byte Count */
+#define USB_COUNT_TX_MASK (0x03ff << USB_COUNT_COUNT_TX_SHIFT)
+
+/* Reception buffer address */
+
+#define USB_ADDR_RX_ZERO (1 << 0) /* Bit 0 This bit must always be written as ‘0’ */
+#define USB_ADDR_RX_SHIFT (1) /* Bits 15:1 ADDRn_RX[15:1]: Reception Buffer Address */
+#define USB_ADDR_RX_MASK (0x7fff << USB_ADDR_RX_SHIFT)
+
+/* Reception byte count */
+
+#define USB_COUNT_RX_BL_SIZE (1 << 15) /* Bit 15: BLock SIZE. */
+#define USB_COUNT_RX_NUM_BLOCK_SHIFT (10) /* Bits 14-10: Number of blocks */
+#define USB_COUNT_RX_NUM_BLOCK_MASK (0x1f << USB_COUNT_RX_NUM_BLOCK_SHIFT)
+#define USB_COUNT_RX_SHIFT (0) /* Bits 9-0: Reception Byte Count */
+#define USB_COUNT_RX_MASK (0x03ff << USB_COUNT_RX_SHIFT)
+
+#endif /* CONFIG_STM32_STM32F10XX */
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_USBDEV_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_wdg.h b/nuttx/arch/arm/src/stm32/chip/stm32_wdg.h
new file mode 100644
index 000000000..5abb5bc6d
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_wdg.h
@@ -0,0 +1,145 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32_wdg.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_CHIP_STM32_WDG_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32_WDG_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_IWDG_KR_OFFSET 0x0000 /* Key register (32-bit) */
+#define STM32_IWDG_PR_OFFSET 0x0004 /* Prescaler register (32-bit) */
+#define STM32_IWDG_RLR_OFFSET 0x0008 /* Reload register (32-bit) */
+#define STM32_IWDG_SR_OFFSET 0x000c /* Status register (32-bit) */
+
+#define STM32_WWDG_CR_OFFSET 0x0000 /* Control Register (32-bit) */
+#define STM32_WWDG_CFR_OFFSET 0x0004 /* Configuration register (32-bit) */
+#define STM32_WWDG_SR_OFFSET 0x0008 /* Status register (32-bit) */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_IWDG_KR (STM32_IWDG_BASE+STM32_IWDG_KR_OFFSET)
+#define STM32_IWDG_PR (STM32_IWDG_BASE+STM32_IWDG_PR_OFFSET)
+#define STM32_IWDG_RLR (STM32_IWDG_BASE+STM32_IWDG_RLR_OFFSET)
+#define STM32_IWDG_SR (STM32_IWDG_BASE+STM32_IWDG_SR_OFFSET)
+
+#define STM32_WWDG_CR (STM32_WWDG_BASE+STM32_WWDG_CR_OFFSET)
+#define STM32_WWDG_CFR (STM32_WWDG_BASE+STM32_WWDG_CFR_OFFSET)
+#define STM32_WWDG_SR (STM32_WWDG_BASE+STM32_WWDG_SR_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* Key register (32-bit) */
+
+#define IWDG_KR_KEY_SHIFT (0) /* Bits 15-0: Key value (write only, read 0000h) */
+#define IWDG_KR_KEY_MASK (0xffff << IWDG_KR_KEY_SHIFT)
+
+#define IWDG_KR_KEY_ENABLE (0x5555) /* Enable register access */
+#define IWDG_KR_KEY_DISABLE (0x0000) /* Disable register access */
+#define IWDG_KR_KEY_RELOAD (0xaaaa) /* Reload the counter */
+#define IWDG_KR_KEY_START (0xcccc) /* Start the watchdog */
+
+/* Prescaler register (32-bit) */
+
+#define IWDG_PR_SHIFT (0) /* Bits 2-0: Prescaler divider */
+#define IWDG_PR_MASK (7 << IWDG_PR_SHIFT)
+# define IWDG_PR_DIV4 (0 << IWDG_PR_SHIFT) /* 000: divider /4 */
+# define IWDG_PR_DIV8 (1 << IWDG_PR_SHIFT) /* 001: divider /8 */
+# define IWDG_PR_DIV16 (2 << IWDG_PR_SHIFT) /* 010: divider /16 */
+# define IWDG_PR_DIV32 (3 << IWDG_PR_SHIFT) /* 011: divider /32 */
+# define IWDG_PR_DIV64 (4 << IWDG_PR_SHIFT) /* 100: divider /64 */
+# define IWDG_PR_DIV128 (5 << IWDG_PR_SHIFT) /* 101: divider /128 */
+# define IWDG_PR_DIV256 (6 << IWDG_PR_SHIFT) /* 11x: divider /256 */
+
+/* Reload register (32-bit) */
+
+#define IWDG_RLR_RL_SHIFT (0) /* Bits11:0 RL[11:0]: Watchdog counter reload value */
+#define IWDG_RLR_RL_MASK (0x0fff << IWDG_RLR_RL_SHIFT)
+
+#define IWDG_RLR_MAX (0xfff)
+
+/* Status register (32-bit) */
+
+#define IWDG_SR_PVU (1 << 0) /* Bit 0: Watchdog prescaler value update */
+#define IWDG_SR_RVU (1 << 1) /* Bit 1: Watchdog counter reload value update */
+
+/* Control Register (32-bit) */
+
+#define WWDG_CR_T_SHIFT (0) /* Bits 6:0 T[6:0]: 7-bit counter (MSB to LSB) */
+#define WWDG_CR_T_MASK (0x7f << WWDG_CR_T_SHIFT)
+# define WWDG_CR_T_MAX (0x3f << WWDG_CR_T_SHIFT)
+# define WWDG_CR_T_RESET (0x40 << WWDG_CR_T_SHIFT)
+#define WWDG_CR_WDGA (1 << 7) /* Bit 7: Activation bit */
+
+/* Configuration register (32-bit) */
+
+#define WWDG_CFR_W_SHIFT (0) /* Bits 6:0 W[6:0] 7-bit window value */
+#define WWDG_CFR_W_MASK (0x7f << WWDG_CFR_W_SHIFT)
+#define WWDG_CFR_WDGTB_SHIFT (7) /* Bits 8:7 [1:0]: Timer Base */
+#define WWDG_CFR_WDGTB_MASK (3 << WWDG_CFR_WDGTB_SHIFT)
+# define WWDG_CFR_PCLK1 (0 << WWDG_CFR_WDGTB_SHIFT) /* 00: CK Counter Clock (PCLK1 div 4096) div 1 */
+# define WWDG_CFR_PCLK1d2 (1 << WWDG_CFR_WDGTB_SHIFT) /* 01: CK Counter Clock (PCLK1 div 4096) div 2 */
+# define WWDG_CFR_PCLK1d4 (2 << WWDG_CFR_WDGTB_SHIFT) /* 10: CK Counter Clock (PCLK1 div 4096) div 4 */
+# define WWDG_CFR_PCLK1d8 (3 << WWDG_CFR_WDGTB_SHIFT) /* 11: CK Counter Clock (PCLK1 div 4096) div 8 */
+#define WWDG_CFR_EWI (1 << 9) /* Bit 9: Early Wakeup Interrupt */
+
+/* Status register (32-bit) */
+
+#define WWDG_SR_EWIF (1 << 0) /* Bit 0: Early Wakeup Interrupt Flag */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_WDG_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f100_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f100_pinmap.h
new file mode 100644
index 000000000..18e8435f7
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f100_pinmap.h
@@ -0,0 +1,267 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f100_pinmap.h
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Copyright (C) 2012 Michael Smith. All Rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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_STM32_CHIP_STM32F100_PINMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F100_PINMAP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* TIMERS */
+
+#if defined(CONFIG_STM32_TIM1_FULL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+#endif
+
+#if defined(CONFIG_STM32_TIM2_FULL_REMAP)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#else
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#endif
+
+#if defined(CONFIG_STM32_TIM3_FULL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#endif
+
+#if defined(CONFIG_STM32_TIM4_REMAP)
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#else
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#endif
+
+/* USART */
+
+#if defined(CONFIG_STM32_USART1_REMAP)
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7)
+#else
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#endif
+
+#if defined(CONFIG_STM32_USART2_REMAP)
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+#else
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+#endif
+
+#if defined(CONFIG_STM32_USART3_FULL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#else
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#endif
+
+/* SPI */
+
+#if defined(CONFIG_STM32_SPI1_REMAP)
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#else
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#endif
+
+#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+
+/* I2C */
+
+#if defined(CONFIG_STM32_I2C1_REMAP)
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#else
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+#endif
+#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+
+#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F100_PINMAP_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f103re_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f103re_pinmap.h
new file mode 100644
index 000000000..7c33da449
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f103re_pinmap.h
@@ -0,0 +1,332 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f103re_pinmap.h
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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_STM32_CHIP_STM32F103RE_PINMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F103RE_PINMAP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* TIMERS */
+
+#if defined(CONFIG_STM32_TIM1_FULL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+#endif
+
+#if defined(CONFIG_STM32_TIM2_FULL_REMAP)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#else
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#endif
+
+#if defined(CONFIG_STM32_TIM3_FULL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#endif
+
+#if defined(CONFIG_STM32_TIM4_REMAP)
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#else
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#endif
+
+#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+
+#define GPIO_TIM8_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM8_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM8_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM8_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM8_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM8_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM8_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM8_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM8_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM8_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM8_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM8_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM8_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+
+/* USART */
+
+#if defined(CONFIG_STM32_USART1_REMAP)
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#else
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#endif
+
+#if defined(CONFIG_STM32_USART2_REMAP)
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+#else
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+#endif
+
+#if defined(CONFIG_STM32_USART3_FULL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#else
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#endif
+
+/* SPI */
+
+#if defined(CONFIG_STM32_SPI1_REMAP)
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#else
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#endif
+
+#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+
+#if defined(CONFIG_STM32_SPI3_REMAP)
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+#else
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#endif
+
+/* I2C */
+
+#if defined(CONFIG_STM32_I2C1_REMAP)
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#else
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+#endif
+#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+
+#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+
+/* CAN */
+
+#if defined(CONFIG_STM32_CAN1_REMAP1)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+#elif defined(CONFIG_STM32_CAN1_REMAP2)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN1)
+#else
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+#endif
+
+
+/* SDIO */
+
+#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+
+#ifndef CONFIG_SDIO_WIDTH_D1_ONLY
+# define GPIO_SDIO_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+# define GPIO_SDIO_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_SDIO_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_SDIO_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_SDIO_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_SDIO_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_SDIO_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+#endif
+
+#define GPIO_SDIO_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN2)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F103RE_PINMAP_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f103vc_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f103vc_pinmap.h
new file mode 100644
index 000000000..c8f33321a
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f103vc_pinmap.h
@@ -0,0 +1,423 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f103vc_pinmap.h
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ * Laurent Latil <laurent@latil.nom.fr>
+ *
+ * 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_STM32_CHIP_STM32F103VC_PINMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F103VC_PINMAP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Alternate Pin Functions: */
+
+#define GPIO_ADC12_IN0 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC12_IN1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC12_IN10 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC12_IN11 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC12_IN12 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC12_IN13 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC12_IN14 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ADC12_IN15 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5)
+#define GPIO_ADC12_IN2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC12_IN3 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC12_IN4 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_ADC12_IN5 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_ADC12_IN6 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_ADC12_IN7 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ADC12_IN8 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ADC12_IN9 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+
+#if defined(CONFIG_STM32_CAN1_FULL_REMAP)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN1)
+#elif defined(CONFIG_STM32_CAN1_PARTIAL_REMAP)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+#else
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+#endif
+
+/* SDIO */
+
+#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+
+#ifndef CONFIG_SDIO_WIDTH_D1_ONLY
+# define GPIO_SDIO_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+# define GPIO_SDIO_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_SDIO_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_SDIO_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_SDIO_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_SDIO_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_SDIO_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+#endif
+
+#define GPIO_SDIO_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN2)
+
+/* FSMC: NOR/PSRAM/SRAM (NPS) */
+#define GPIO_NPS_A16 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11)
+#define GPIO_NPS_A17 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_NPS_A18 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13)
+#define GPIO_NPS_A19 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_NPS_A20 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_NPS_A21 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_NPS_A22 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_NPS_A23 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2)
+
+#define GPIO_NPS_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_NPS_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_NPS_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_NPS_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_NPS_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7)
+#define GPIO_NPS_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_NPS_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_NPS_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_NPS_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_NPS_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_NPS_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_NPS_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_NPS_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_NPS_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+#define GPIO_NPS_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_NPS_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+
+#define GPIO_NPS_CLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN3)
+#define GPIO_NPS_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_NPS_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+#define GPIO_NPS_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_NPS_NE1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+
+
+#if 0 /* Needs further investigation */
+#define GPIO_DAC_OUT1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUTz|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_DAC_OUT2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5)
+#endif
+
+#if defined(CONFIG_STM32_I2C1_REMAP)
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#else
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+#endif
+#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+
+#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+
+#define GPIO_I2S2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_I2S2_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+
+#define GPIO_I2S3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_I2S3_SD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_I2S3_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+
+#if 0 /* Needs further investigation */
+#define GPIO_MCO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_OTG_FSDM (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_OTG_FSDP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_OTG_FSID (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_OTG_FSSOF (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_OTG_FSVBUS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+#endif
+
+#if defined(CONFIG_STM32_SPI1_REMAP)
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#else
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#endif
+
+#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+
+#if defined(CONFIG_STM32_SPI3_REMAP)
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+#else
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_TAMPER_RTC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN13)
+#endif
+
+#if defined(CONFIG_STM32_TIM1_FULL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+#endif
+
+#if defined(CONFIG_STM32_TIM2_FULL_REMAP)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#else
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#endif
+
+#if defined(CONFIG_STM32_TIM3_FULL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#endif
+#define GPIO_TIM3_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2)
+
+#if defined(CONFIG_STM32_TIM4_REMAP)
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#else
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#endif
+#define GPIO_TIM4_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN0)
+
+#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH4IN (GGPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+
+#if 0 /* Needs further investigation */
+#define GPIO_TRACECK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_TRACED0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_TRACED1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_TRACED2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_TRACED3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6)
+#if defined(CONFIG_STM32_TRACESWO_REMAP)
+# define GPIO_TRACESWO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+#endif
+#endif
+
+#define GPIO_USART1_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_USART1_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_USART1_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+#if defined(CONFIG_STM32_USART1_REMAP)
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+#else
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#endif
+
+#if defined(CONFIG_STM32_USART2_REMAP)
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+#else
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+#endif
+
+#if defined(CONFIG_STM32_USART3_FULL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#else
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#endif
+
+#define GPIO_UART4_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_UART4_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+
+#define GPIO_UART5_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2)
+#define GPIO_UART5_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+
+#define GPIO_WKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+
+/* Some GPIOs are accessible only as remapped, alternate functions */
+
+#if 0 /* Needs further investigation */
+#define GPIO_PA13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN13)
+#define GPIO_PA14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN14)
+#define GPIO_PA15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_PB3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_PB4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4)
+#endif
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F103VC_PINMAP_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h
new file mode 100644
index 000000000..4a320e1fd
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f103ze_pinmap.h
@@ -0,0 +1,583 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f103ze_pinmap.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_CHIP_STM32F103ZE_PINMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F103ZE_PINMAP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Alternate Pin Functions: */
+
+/* ADC */
+
+#define GPIO_ADC1_IN0 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC1_IN1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC1_IN2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC1_IN3 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC1_IN4 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_ADC1_IN5 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_ADC1_IN6 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_ADC1_IN7 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ADC1_IN8 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ADC1_IN9 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_ADC1_IN10 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC1_IN11 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC1_IN12 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC1_IN13 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC1_IN14 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ADC1_IN15 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5)
+
+#define GPIO_ADC2_IN0 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC2_IN1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC2_IN2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC2_IN3 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC2_IN4 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_ADC2_IN5 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_ADC2_IN6 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_ADC2_IN7 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ADC2_IN8 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ADC2_IN9 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_ADC2_IN10 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC2_IN11 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC2_IN12 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC2_IN13 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC2_IN14 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ADC2_IN15 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5)
+
+#define GPIO_ADC3_IN0 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC3_IN1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC3_IN2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC3_IN3 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC3_IN4 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN6)
+#define GPIO_ADC3_IN5 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN7)
+#define GPIO_ADC3_IN6 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN8)
+#define GPIO_ADC3_IN7 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN9)
+#define GPIO_ADC3_IN8 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10)
+#define GPIO_ADC3_IN10 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC3_IN11 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC3_IN12 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC3_IN13 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3)
+
+/* DAC - "Once the DAC channelx is enabled, the corresponding GPIO pin
+ * (PA4 or PA5) is automatically connected to the analog converter output
+ * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin
+ * should first be configured to analog (AIN)."
+ */
+
+#define GPIO_DAC_OUT1 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10)
+#define GPIO_DAC_OUT2 (GPIO_ALT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PIN10)
+
+/* TIMERS */
+
+#if defined(CONFIG_STM32_TIM1_FULL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+#endif
+
+#if defined(CONFIG_STM32_TIM2_FULL_REMAP)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#else
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#endif
+
+#if defined(CONFIG_STM32_TIM3_FULL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#endif
+
+#if defined(CONFIG_STM32_TIM4_REMAP)
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#else
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#endif
+
+#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+
+#define GPIO_TIM8_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM8_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM8_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM8_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM8_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM8_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM8_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM8_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM8_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM8_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM8_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM8_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM8_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+
+/* USART */
+
+#if defined(CONFIG_STM32_USART1_REMAP)
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#else
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#endif
+
+#if defined(CONFIG_STM32_USART2_REMAP)
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+#else
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+#endif
+
+#if defined(CONFIG_STM32_USART3_FULL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#else
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#endif
+
+/* SPI */
+
+#if defined(CONFIG_STM32_SPI1_REMAP)
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#else
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#endif
+
+#if defined(CONFIG_STM32_SPI3_REMAP)
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+#else
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#endif
+
+/* I2C */
+
+#if defined(CONFIG_STM32_I2C1_REMAP)
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#else
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+#endif
+
+#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+
+#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_INFLOAT|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+
+/* CAN */
+
+#if defined(CONFIG_STM32_CAN1_REMAP1)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8)
+#elif defined(CONFIG_STM32_CAN1_REMAP2)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN0)
+#else
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+#endif
+
+/* FSMC: CF */
+
+#define GPIO_CF_A0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN0)
+#define GPIO_CF_A1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN1)
+#define GPIO_CF_A2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN2)
+#define GPIO_CF_A3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN3)
+#define GPIO_CF_A4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN4)
+#define GPIO_CF_A5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN5)
+#define GPIO_CF_A6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN12)
+#define GPIO_CF_A7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN13)
+#define GPIO_CF_A8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN14)
+#define GPIO_CF_A9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN15)
+#define GPIO_CF_A10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN0)
+#define GPIO_CF_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_CF_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_CF_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_CF_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_CF_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7)
+#define GPIO_CF_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_CF_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_CF_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_CF_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_CF_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_CF_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_CF_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_CF_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_CF_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+#define GPIO_CF_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_CF_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+#define GPIO_CF_NIORD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN6)
+#define GPIO_CF_NREG (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN7)
+#define GPIO_CF_NIOWR (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN8)
+#define GPIO_CF_CD (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN9)
+#define GPIO_CF_INTR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10)
+#define GPIO_CF_NIOS16 (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN11)
+#define GPIO_CF_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_CF_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+#define GPIO_CF_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_CF_NCE41 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN10)
+#define GPIO_CF_NCE42 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN11)
+
+/* FSMC: CF/IDE */
+
+#define GPIO_CFIDE_A0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN0)
+#define GPIO_CFIDE_A1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN1)
+#define GPIO_CFIDE_A2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN2)
+#define GPIO_CFIDE_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_CFIDE_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_CFIDE_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_CFIDE_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_CFIDE_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7)
+#define GPIO_CFIDE_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_CFIDE_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_CFIDE_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_CFIDE_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_CFIDE_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_CFIDE_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_CFIDE_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_CFIDE_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_CFIDE_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+#define GPIO_CFIDE_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_CFIDE_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+#define GPIO_CFIDE_NIORD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN6)
+#define GPIO_CFIDE_NREG (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN7)
+#define GPIO_CFIDE_NIOWR (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN8)
+#define GPIO_CFIDE_CD (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN9)
+#define GPIO_CFIDE_INTR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN10)
+#define GPIO_CFIDE_NIOS16 (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTF|GPIO_PIN11)
+#define GPIO_CFIDE_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_CFIDE_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+#define GPIO_CFIDE_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_CFIDE_NCE41 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN10)
+#define GPIO_CFIDE_NCE42 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN11)
+
+/* SDIO */
+
+#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+
+#ifndef CONFIG_SDIO_WIDTH_D1_ONLY
+# define GPIO_SDIO_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+# define GPIO_SDIO_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_SDIO_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_SDIO_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_SDIO_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_SDIO_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_SDIO_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+#endif
+
+#define GPIO_SDIO_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN2)
+
+/* FSMC: NOR/PSRAM/SRAM (NPS) */
+
+#define GPIO_NPS_A0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN0)
+#define GPIO_NPS_A1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN1)
+#define GPIO_NPS_A2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN2)
+#define GPIO_NPS_A3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN3)
+#define GPIO_NPS_A4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN4)
+#define GPIO_NPS_A5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN5)
+#define GPIO_NPS_A6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN12)
+#define GPIO_NPS_A7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN13)
+#define GPIO_NPS_A8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN14)
+#define GPIO_NPS_A9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTF|GPIO_PIN15)
+#define GPIO_NPS_A10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN0)
+#define GPIO_NPS_A11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN1)
+#define GPIO_NPS_A12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN2)
+#define GPIO_NPS_A13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN3)
+#define GPIO_NPS_A14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN4)
+#define GPIO_NPS_A15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN5)
+#define GPIO_NPS_A16 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11)
+#define GPIO_NPS_A17 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_NPS_A18 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13)
+#define GPIO_NPS_A19 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_NPS_A20 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_NPS_A21 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_NPS_A22 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_NPS_A23 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_NPS_A24 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_NPS_A25 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN14)
+#define GPIO_NPS_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_NPS_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_NPS_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_NPS_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_NPS_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7)
+#define GPIO_NPS_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_NPS_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_NPS_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_NPS_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_NPS_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_NPS_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_NPS_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_NPS_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_NPS_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+#define GPIO_NPS_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_NPS_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+#define GPIO_NPS_CLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN3)
+#define GPIO_NPS_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_NPS_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+#define GPIO_NPS_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_NPS_NE1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+#define GPIO_NPS_NE2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN9)
+#define GPIO_NPS_NE3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN10)
+#define GPIO_NPS_NE4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN12)
+#define GPIO_NPS_NBL0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN0)
+#define GPIO_NPS_NBL1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN1)
+
+/* FSMC: NOR/PSRAM Multiplex (NPM) */
+
+#define GPIO_NPM_A16 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11)
+#define GPIO_NPM_A17 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_NPM_A18 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13)
+#define GPIO_NPM_A19 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_NPM_A20 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_NPM_A21 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_NPM_A22 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_NPM_A23 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_NPM_DA0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_NPM_DA1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_NPM_DA2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_NPM_DA3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_NPM_DA4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7)
+#define GPIO_NPM_DA5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_NPM_DA6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_NPM_DA7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_NPM_DA8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_NPM_DA9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_NPM_DA10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_NPM_DA11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_NPM_DA12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_NPM_DA13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+#define GPIO_NPM_DA14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_NPM_DA15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+#define GPIO_NPM_CLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN3)
+#define GPIO_NPM_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_NPM_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+#define GPIO_NPM_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_NPM_NE1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+#define GPIO_NPM_NE2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN9)
+#define GPIO_NPM_NE3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN10)
+#define GPIO_NPM_NE4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN12)
+#define GPIO_NPM_A24 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_NPM_A25 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN14)
+#define GPIO_NPM_NBL0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN0)
+#define GPIO_NPM_NBL1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN1)
+
+/* FSMC: NAND */
+
+#define GPIO_NAND_D4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN7)
+#define GPIO_NAND_D5 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_NAND_D6 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_NAND_D7 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_NAND_D8 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_NAND_D9 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_NAND_D10 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_NAND_D11 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_NAND_D12 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_NAND_D13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+#define GPIO_NAND_D14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_NAND_D15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+#define GPIO_NAND_CLE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11)
+#define GPIO_NAND_ALE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_NAND_D0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_NAND_D1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_NAND_INT2 (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTG|GPIO_PIN6)
+#define GPIO_NAND_INT3 (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTG|GPIO_PIN7)
+#define GPIO_NAND_D2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_NAND_D3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_NAND_NOE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_NAND_NWE (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+#define GPIO_NAND_NWAIT (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_NAND_NCE2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+#define GPIO_NAND_NCE3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTG|GPIO_PIN9)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F103ZE_PINMAP_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f105vb_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f105vb_pinmap.h
new file mode 100644
index 000000000..81f621dd9
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f105vb_pinmap.h
@@ -0,0 +1,416 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f105vb_pinmap.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_CHIP_STM32F105VB_PINMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F105VB_PINMAP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Alternate Pin Functions: */
+
+#define GPIO_ADC12_IN0 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC12_IN1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC12_IN10 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC12_IN11 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC12_IN12 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC12_IN13 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC12_IN14 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ADC12_IN15 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5)
+#define GPIO_ADC12_IN2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC12_IN3 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC12_IN4 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_ADC12_IN5 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_ADC12_IN6 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_ADC12_IN7 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ADC12_IN8 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ADC12_IN9 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+
+#if defined(CONFIG_STM32_CAN1_FULL_REMAP)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN1)
+#elif defined(CONFIG_STM32_CAN1_PARTIAL_REMAP)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+#else
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+#endif
+
+#if defined(CONFIG_STM32_CAN2_REMAP)
+# define GPIO_CAN2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_CAN2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6)
+#else
+# define GPIO_CAN2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_CAN2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_DAC_OUT1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUTz|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_DAC_OUT2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_ETH_MDC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ETH_MDIO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ETH_MIICOL (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ETH_MIICRSWKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ETH_MIIRXCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+
+#if defined(CONFIG_STM32_ETH_REMAP)
+# define GPIO_ETH_MIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9)
+# define GPIO_ETH_MIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+# define GPIO_ETH_MIIRXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11)
+# define GPIO_ETH_MIIRXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_ETH_MIIRXDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+#else
+# define GPIO_ETH_MIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN4)
+# define GPIO_ETH_MIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN5)
+# define GPIO_ETH_MIIRXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_ETH_MIIRXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_ETH_MIIRXDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#endif
+
+#define GPIO_ETH_MIIRXER (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_ETH_MIITXCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ETH_MIITXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_ETH_MIITXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_ETH_MIITXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ETH_MIITXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_ETH_MIITXEN (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_ETH_PPSOUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_ETH_RMIICRSDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ETH_RMIIREFCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ETH_RMIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ETH_RMIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN5)
+#define GPIO_ETH_RMIITXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_ETH_RMIITXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_ETH_RMIITXEN (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#endif
+
+#if defined(CONFIG_STM32_I2C1_REMAP)
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#else
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+#endif
+#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+
+#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_I2S2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_I2S2_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+
+#define GPIO_I2S3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_I2S3_SD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_I2S3_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+
+#if 0 /* Needs further investigation */
+#define GPIO_MCO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_OTG_FSDM (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_OTG_FSDP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_OTG_FSID (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_OTG_FSSOF (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_OTG_FSVBUS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+#endif
+
+#if defined(CONFIG_STM32_SPI1_REMAP)
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#else
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#endif
+
+#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+
+#if defined(CONFIG_STM32_SPI3_REMAP)
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+#else
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_TAMPER_RTC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN13)
+#endif
+
+#if defined(CONFIG_STM32_TIM1_FULL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+#endif
+
+#if defined(CONFIG_STM32_TIM2_FULL_REMAP)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#else
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#endif
+
+#if defined(CONFIG_STM32_TIM3_FULL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#endif
+#define GPIO_TIM3_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2)
+
+#if defined(CONFIG_STM32_TIM4_REMAP)
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#else
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#endif
+#define GPIO_TIM4_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN0)
+
+#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH4IN (GGPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+
+#if 0 /* Needs further investigation */
+#define GPIO_TRACECK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_TRACED0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_TRACED1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_TRACED2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_TRACED3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6)
+#if defined(CONFIG_STM32_TRACESWO_REMAP)
+# define GPIO_TRACESWO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+#endif
+#endif
+
+#define GPIO_USART1_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_USART1_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_USART1_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+#if defined(CONFIG_STM32_USART1_REMAP)
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#else
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#endif
+
+#if defined(CONFIG_STM32_USART2_REMAP)
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+#else
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+#endif
+
+#if defined(CONFIG_STM32_USART3_FULL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#else
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#endif
+
+#define GPIO_UART4_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_UART4_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+
+#define GPIO_UART5_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2)
+#define GPIO_UART5_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+
+#define GPIO_WKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+
+/* Some GPIOs are accessible only as remapped, alternate functions */
+
+#if 0 /* Needs further investigation */
+#define GPIO_PA13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN13)
+#define GPIO_PA14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN14)
+#define GPIO_PA15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_PB3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_PB4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4)
+#endif
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F105VB_PINMAP_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f107vc_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f107vc_pinmap.h
new file mode 100644
index 000000000..0b46d79fa
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f107vc_pinmap.h
@@ -0,0 +1,416 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f107vc_pinmap.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_CHIP_STM32F107VC_PINMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F107VC_PINMAP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Alternate Pin Functions: */
+
+#define GPIO_ADC12_IN0 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC12_IN1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC12_IN10 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC12_IN11 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC12_IN12 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC12_IN13 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC12_IN14 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ADC12_IN15 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN5)
+#define GPIO_ADC12_IN2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC12_IN3 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC12_IN4 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_ADC12_IN5 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_ADC12_IN6 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_ADC12_IN7 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ADC12_IN8 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ADC12_IN9 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+
+#if defined(CONFIG_STM32_CAN1_FULL_REMAP)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN0)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN1)
+#elif defined(CONFIG_STM32_CAN1_PARTIAL_REMAP)
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+#else
+# define GPIO_CAN1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_CAN1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+#endif
+
+#if defined(CONFIG_STM32_CAN2_REMAP)
+# define GPIO_CAN2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_CAN2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6)
+#else
+# define GPIO_CAN2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_CAN2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_DAC_OUT1 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUTz|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_DAC_OUT2 (GPIO_INPUT|GPIO_CNF_ANALOGIN|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN5)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_ETH_MDC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ETH_MDIO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ETH_MIICOL (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ETH_MIICRSWKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ETH_MIIRXCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+
+#if defined(CONFIG_STM32_ETH_REMAP)
+# define GPIO_ETH_MIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN9)
+# define GPIO_ETH_MIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+# define GPIO_ETH_MIIRXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN11)
+# define GPIO_ETH_MIIRXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_ETH_MIIRXDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+#else
+# define GPIO_ETH_MIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN4)
+# define GPIO_ETH_MIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN5)
+# define GPIO_ETH_MIIRXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_ETH_MIIRXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_ETH_MIIRXDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#endif
+
+#define GPIO_ETH_MIIRXER (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_ETH_MIITXCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ETH_MIITXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_ETH_MIITXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_ETH_MIITXD2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ETH_MIITXD3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_ETH_MIITXEN (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_ETH_PPSOUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_ETH_RMIICRSDV (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ETH_RMIIREFCLK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ETH_RMIIRXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ETH_RMIIRXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN5)
+#define GPIO_ETH_RMIITXD0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_ETH_RMIITXD1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_ETH_RMIITXEN (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#endif
+
+#if defined(CONFIG_STM32_I2C1_REMAP)
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#else
+# define GPIO_I2C1_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_I2C1_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+#endif
+#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+
+#define GPIO_I2C2_SCL (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2C2_SDA (GPIO_ALT|GPIO_CNF_AFOD|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_I2C2_SMBA (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_I2S2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_I2S2_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+
+#define GPIO_I2S3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_I2S3_SD (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_I2S3_WS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+
+#if 0 /* Needs further investigation */
+#define GPIO_MCO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_OTG_FSDM (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_OTG_FSDP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_OTG_FSID (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_OTG_FSSOF (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_OTG_FSVBUS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+#endif
+
+#if defined(CONFIG_STM32_SPI1_REMAP)
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#else
+# define GPIO_SPI1_NSS (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI1_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN5)
+# define GPIO_SPI1_MISO (GPIO_INPUT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_SPI1_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+#endif
+
+#define GPIO_SPI2_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_SPI2_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_SPI2_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_SPI2_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+
+#if defined(CONFIG_STM32_SPI3_REMAP)
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN4)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+#else
+# define GPIO_SPI3_NSS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_SPI3_SCK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_SPI3_MISO (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_SPI3_MOSI (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+#endif
+
+#if 0 /* Needs further investigation */
+#define GPIO_TAMPER_RTC (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN13)
+#endif
+
+#if defined(CONFIG_STM32_TIM1_FULL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN7)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN9)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN11)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN13)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN14)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN15)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN8)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN10)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN12)
+#elif defined(CONFIG_STM32_TIM1_PARTIAL_REMAP)
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM1_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN12)
+# define GPIO_TIM1_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+# define GPIO_TIM1_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_TIM1_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN10)
+# define GPIO_TIM1_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN11)
+# define GPIO_TIM1_BKIN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_TIM1_CH1N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_TIM1_CH2N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+# define GPIO_TIM1_CH3N (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN15)
+#endif
+
+#if defined(CONFIG_STM32_TIM2_FULL_REMAP)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_1)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#elif defined(CONFIG_STM32_TIM2_PARTIAL_REMAP_2)
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN11)
+#else
+# define GPIO_TIM2_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_TIM2_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_TIM2_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_TIM2_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_TIM2_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+#endif
+
+#if defined(CONFIG_STM32_TIM3_FULL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN8)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN9)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN9)
+#elif defined(CONFIG_STM32_TIM3_PARTIAL_REMAP)
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN5)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#else
+# define GPIO_TIM3_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN6)
+# define GPIO_TIM3_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN7)
+# define GPIO_TIM3_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN0)
+# define GPIO_TIM3_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN1)
+# define GPIO_TIM3_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN1)
+#endif
+#define GPIO_TIM3_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2)
+
+#if defined(CONFIG_STM32_TIM4_REMAP)
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN13)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN14)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN15)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN15)
+#else
+# define GPIO_TIM4_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN6)
+# define GPIO_TIM4_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN7)
+# define GPIO_TIM4_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN8)
+# define GPIO_TIM4_CH4IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN9)
+# define GPIO_TIM4_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN9)
+#endif
+#define GPIO_TIM4_ETR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTE|GPIO_PIN0)
+
+#define GPIO_TIM5_CH1IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH1OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH2IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH2OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH3IN (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH3OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH4IN (GGPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM5_CH4OUT (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN3)
+
+#if 0 /* Needs further investigation */
+#define GPIO_TRACECK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_TRACED0 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_TRACED1 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_TRACED2 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_TRACED3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTE|GPIO_PIN6)
+#if defined(CONFIG_STM32_TRACESWO_REMAP)
+# define GPIO_TRACESWO (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+#endif
+#endif
+
+#define GPIO_USART1_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_USART1_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_USART1_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN8)
+#if defined(CONFIG_STM32_USART1_REMAP)
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#else
+# define GPIO_USART1_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN9)
+# define GPIO_USART1_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN10)
+#endif
+
+#if defined(CONFIG_STM32_USART2_REMAP)
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN3)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN4)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN5)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN6)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN7)
+#else
+# define GPIO_USART2_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN0)
+# define GPIO_USART2_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN1)
+# define GPIO_USART2_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN2)
+# define GPIO_USART2_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTA|GPIO_PIN3)
+# define GPIO_USART2_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN4)
+#endif
+
+#if defined(CONFIG_STM32_USART3_FULL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN8)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN9)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN10)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN11)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTD|GPIO_PIN12)
+#elif defined(CONFIG_STM32_USART3_PARTIAL_REMAP)
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#else
+# define GPIO_USART3_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN10)
+# define GPIO_USART3_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN11)
+# define GPIO_USART3_CK (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN12)
+# define GPIO_USART3_CTS (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTB|GPIO_PIN13)
+# define GPIO_USART3_RTS (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN14)
+#endif
+
+#define GPIO_UART4_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_UART4_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN10)
+
+#define GPIO_UART5_RX (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|GPIO_PORTD|GPIO_PIN2)
+#define GPIO_UART5_TX (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTC|GPIO_PIN12)
+
+#define GPIO_WKUP (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN0)
+
+/* Some GPIOs are accessible only as remapped, alternate functions */
+
+#if 0 /* Needs further investigation */
+#define GPIO_PA13 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN13)
+#define GPIO_PA14 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN14)
+#define GPIO_PA15 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_PB3 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_PB4 (GPIO_ALT|GPIO_CNF_AFPP|GPIO_MODE_50MHz|GPIO_PORTB|GPIO_PIN4)
+#endif
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F107VC_PINMAP_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_dma.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_dma.h
new file mode 100644
index 000000000..a8241bc72
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_dma.h
@@ -0,0 +1,350 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f10xxx_dma.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_CHIP_STM32F10XXX_DMA_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_DMA_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* 7 DMA Channels */
+
+#define DMA1 0
+#define DMA2 1
+#define DMA3 2
+#define DMA4 3
+#define DMA5 4
+#define DMA6 5
+#define DMA7 6
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_DMA_ISR_OFFSET 0x0000 /* DMA interrupt status register */
+#define STM32_DMA_IFCR_OFFSET 0x0004 /* DMA interrupt flag clear register */
+
+#define STM32_DMACHAN_OFFSET(n) (0x0014*(n))
+#define STM32_DMACHAN_CCR_OFFSET 0x0008
+#define STM32_DMACHAN_CNDTR_OFFSET 0x000c
+#define STM32_DMACHAN_CPAR_OFFSET 0x0010
+#define STM32_DMACHAN_CMAR_OFFSET 0x0014
+
+#define STM32_DMA_CCR_OFFSET(n) (STM32_DMACHAN_CCR_OFFSET+STM32_DMACHAN_OFFSET(n))
+#define STM32_DMA_CNDTR_OFFSET(n) (STM32_DMACHAN_CNDTR_OFFSET+STM32_DMACHAN_OFFSET(n))
+#define STM32_DMA_CPAR_OFFSET(n) (STM32_DMACHAN_CPAR_OFFSET+STM32_DMACHAN_OFFSET(n))
+#define STM32_DMA_CMAR_OFFSET(n) (STM32_DMACHAN_CMAR_OFFSET+STM32_DMACHAN_OFFSET(n))
+
+#define STM32_DMA_CCR1_OFFSET 0x0008 /* DMA channel 1 configuration register */
+#define STM32_DMA_CCR2_OFFSET 0x001c /* DMA channel 2 configuration register */
+#define STM32_DMA_CCR3_OFFSET 0x0030 /* DMA channel 3 configuration register */
+#define STM32_DMA_CCR4_OFFSET 0x0044 /* DMA channel 4 configuration register */
+#define STM32_DMA_CCR5_OFFSET 0x0058 /* DMA channel 5 configuration register */
+#define STM32_DMA_CCR6_OFFSET 0x006c /* DMA channel 6 configuration register */
+#define STM32_DMA_CCR7_OFFSET 0x0080 /* DMA channel 7 configuration register */
+
+#define STM32_DMA_CNDTR1_OFFSET 0x000c /* DMA channel 1 number of data register */
+#define STM32_DMA_CNDTR2_OFFSET 0x0020 /* DMA channel 2 number of data register */
+#define STM32_DMA_CNDTR3_OFFSET 0x0034 /* DMA channel 3 number of data register */
+#define STM32_DMA_CNDTR4_OFFSET 0x0048 /* DMA channel 4 number of data register */
+#define STM32_DMA_CNDTR5_OFFSET 0x005c /* DMA channel 5 number of data register */
+#define STM32_DMA_CNDTR6_OFFSET 0x0070 /* DMA channel 6 number of data register */
+#define STM32_DMA_CNDTR7_OFFSET 0x0084 /* DMA channel 7 number of data register */
+
+#define STM32_DMA_CPAR1_OFFSET 0x0010 /* DMA channel 1 peripheral address register */
+#define STM32_DMA_CPAR2_OFFSET 0x0024 /* DMA channel 2 peripheral address register */
+#define STM32_DMA_CPAR3_OFFSET 0x0038 /* DMA channel 3 peripheral address register */
+#define STM32_DMA_CPAR4_OFFSET 0x004c /* DMA channel 4 peripheral address register */
+#define STM32_DMA_CPAR5_OFFSET 0x0060 /* DMA channel 5 peripheral address register */
+#define STM32_DMA_CPAR6_OFFSET 0x0074 /* DMA channel 6 peripheral address register */
+#define STM32_DMA_CPAR7_OFFSET 0x0088 /* DMA channel 7 peripheral address register */
+
+#define STM32_DMA_CMAR1_OFFSET 0x0014 /* DMA channel 1 memory address register */
+#define STM32_DMA_CMAR2_OFFSET 0x0028 /* DMA channel 2 memory address register */
+#define STM32_DMA_CMAR3_OFFSET 0x003c /* DMA channel 3 memory address register */
+#define STM32_DMA_CMAR4_OFFSET 0x0050 /* DMA channel 4 memory address register */
+#define STM32_DMA_CMAR5_OFFSET 0x0064 /* DMA channel 5 memory address register */
+#define STM32_DMA_CMAR6_OFFSET 0x0078 /* DMA channel 6 memory address register */
+#define STM32_DMA_CMAR7_OFFSET 0x008c /* DMA channel 7 memory address register */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_DMA1_ISRC (STM32_DMA1_BASE+STM32_DMA_ISR_OFFSET)
+#define STM32_DMA1_IFCR (STM32_DMA1_BASE+STM32_DMA_IFCR_OFFSET)
+
+#define STM32_DMA1_CCR(n) (STM32_DMA1_BASE+STM32_DMA_CCR_OFFSET(n))
+#define STM32_DMA1_CCR1 (STM32_DMA1_BASE+STM32_DMA_CCR1_OFFSET)
+#define STM32_DMA1_CCR2 (STM32_DMA1_BASE+STM32_DMA_CCR2_OFFSET)
+#define STM32_DMA1_CCR3 (STM32_DMA1_BASE+STM32_DMA_CCR3_OFFSET)
+#define STM32_DMA1_CCR4 (STM32_DMA1_BASE+STM32_DMA_CCR4_OFFSET)
+#define STM32_DMA1_CCR5 (STM32_DMA1_BASE+STM32_DMA_CCR5_OFFSET)
+#define STM32_DMA1_CCR6 (STM32_DMA1_BASE+STM32_DMA_CCR6_OFFSET)
+#define STM32_DMA1_CCR7 (STM32_DMA1_BASE+STM32_DMA_CCR7_OFFSET)
+
+#define STM32_DMA1_CNDTR(n) (STM32_DMA1_BASE+STM32_DMA_CNDTR_OFFSET(n))
+#define STM32_DMA1_CNDTR1 (STM32_DMA1_BASE+STM32_DMA_CNDTR1_OFFSET)
+#define STM32_DMA1_CNDTR2 (STM32_DMA1_BASE+STM32_DMA_CNDTR2_OFFSET)
+#define STM32_DMA1_CNDTR3 (STM32_DMA1_BASE+STM32_DMA_CNDTR3_OFFSET)
+#define STM32_DMA1_CNDTR4 (STM32_DMA1_BASE+STM32_DMA_CNDTR4_OFFSET)
+#define STM32_DMA1_CNDTR5 (STM32_DMA1_BASE+STM32_DMA_CNDTR5_OFFSET)
+#define STM32_DMA1_CNDTR6 (STM32_DMA1_BASE+STM32_DMA_CNDTR6_OFFSET)
+#define STM32_DMA1_CNDTR7 (STM32_DMA1_BASE+STM32_DMA_CNDTR7_OFFSET)
+
+#define STM32_DMA1_CPAR(n) (STM32_DMA1_BASE+STM32_DMA_CPAR_OFFSET(n))
+#define STM32_DMA1_CPAR1 (STM32_DMA1_BASE+STM32_DMA_CPAR1_OFFSET)
+#define STM32_DMA1_CPAR2 (STM32_DMA1_BASE+STM32_DMA_CPAR2_OFFSET)
+#define STM32_DMA1_CPAR3 (STM32_DMA1_BASE+STM32_DMA_CPAR3_OFFSET)
+#define STM32_DMA1_CPAR4 (STM32_DMA1_BASE+STM32_DMA_CPAR4_OFFSET)
+#define STM32_DMA1_CPAR5 (STM32_DMA1_BASE+STM32_DMA_CPAR5_OFFSET)
+#define STM32_DMA1_CPAR6 (STM32_DMA1_BASE+STM32_DMA_CPAR6_OFFSET)
+#define STM32_DMA1_CPAR7 (STM32_DMA1_BASE+STM32_DMA_CPAR7_OFFSET)
+
+#define STM32_DMA1_CMAR(n) (STM32_DMA1_BASE+STM32_DMA_CMAR_OFFSET(n))
+#define STM32_DMA1_CMAR1 (STM32_DMA1_BASE+STM32_DMA_CMAR1_OFFSET)
+#define STM32_DMA1_CMAR2 (STM32_DMA1_BASE+STM32_DMA_CMAR2_OFFSET)
+#define STM32_DMA1_CMAR3 (STM32_DMA1_BASE+STM32_DMA_CMAR3_OFFSET)
+#define STM32_DMA1_CMAR4 (STM32_DMA1_BASE+STM32_DMA_CMAR4_OFFSET)
+#define STM32_DMA1_CMAR5 (STM32_DMA1_BASE+STM32_DMA_CMAR5_OFFSET)
+#define STM32_DMA1_CMAR6 (STM32_DMA1_BASE+STM32_DMA_CMAR6_OFFSET)
+#define STM32_DMA1_CMAR7 (STM32_DMA1_BASE+STM32_DMA_CMAR7_OFFSET)
+
+#define STM32_DMA2_ISRC (STM32_DMA2_BASE+STM32_DMA_ISR_OFFSET)
+#define STM32_DMA2_IFCR (STM32_DMA2_BASE+STM32_DMA_IFCR_OFFSET)
+
+#define STM32_DMA2_CCR(n) (STM32_DMA2_BASE+STM32_DMA_CCR_OFFSET(n))
+#define STM32_DMA2_CCR1 (STM32_DMA2_BASE+STM32_DMA_CCR1_OFFSET)
+#define STM32_DMA2_CCR2 (STM32_DMA2_BASE+STM32_DMA_CCR2_OFFSET)
+#define STM32_DMA2_CCR3 (STM32_DMA2_BASE+STM32_DMA_CCR3_OFFSET)
+#define STM32_DMA2_CCR4 (STM32_DMA2_BASE+STM32_DMA_CCR4_OFFSET)
+#define STM32_DMA2_CCR5 (STM32_DMA2_BASE+STM32_DMA_CCR5_OFFSET)
+
+#define STM32_DMA2_CNDTR(n) (STM32_DMA2_BASE+STM32_DMA_CNDTR_OFFSET(n))
+#define STM32_DMA2_CNDTR1 (STM32_DMA2_BASE+STM32_DMA_CNDTR1_OFFSET)
+#define STM32_DMA2_CNDTR2 (STM32_DMA2_BASE+STM32_DMA_CNDTR2_OFFSET)
+#define STM32_DMA2_CNDTR3 (STM32_DMA2_BASE+STM32_DMA_CNDTR3_OFFSET)
+#define STM32_DMA2_CNDTR4 (STM32_DMA2_BASE+STM32_DMA_CNDTR4_OFFSET)
+#define STM32_DMA2_CNDTR5 (STM32_DMA2_BASE+STM32_DMA_CNDTR5_OFFSET)
+
+#define STM32_DMA2_CPAR(n) (STM32_DMA2_BASE+STM32_DMA_CPAR_OFFSET(n))
+#define STM32_DMA2_CPAR1 (STM32_DMA2_BASE+STM32_DMA_CPAR1_OFFSET)
+#define STM32_DMA2_CPAR2 (STM32_DMA2_BASE+STM32_DMA_CPAR2_OFFSET)
+#define STM32_DMA2_CPAR3 (STM32_DMA2_BASE+STM32_DMA_CPAR3_OFFSET)
+#define STM32_DMA2_CPAR4 (STM32_DMA2_BASE+STM32_DMA_CPAR4_OFFSET)
+#define STM32_DMA2_CPAR5 (STM32_DMA2_BASE+STM32_DMA_CPAR5_OFFSET)
+
+#define STM32_DMA2_CMAR(n) (STM32_DMA2_BASE+STM32_DMA_CMAR_OFFSET(n))
+#define STM32_DMA2_CMAR1 (STM32_DMA2_BASE+STM32_DMA_CMAR1_OFFSET)
+#define STM32_DMA2_CMAR2 (STM32_DMA2_BASE+STM32_DMA_CMAR2_OFFSET)
+#define STM32_DMA2_CMAR3 (STM32_DMA2_BASE+STM32_DMA_CMAR3_OFFSET)
+#define STM32_DMA2_CMAR4 (STM32_DMA2_BASE+STM32_DMA_CMAR4_OFFSET)
+#define STM32_DMA2_CMAR5 (STM32_DMA2_BASE+STM32_DMA_CMAR5_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+#define DMA_CHAN_SHIFT(n) ((n) << 2)
+#define DMA_CHAN_MASK 0x0f
+#define DMA_CHAN_GIF_BIT (1 << 0) /* Bit 0: Channel Global interrupt flag */
+#define DMA_CHAN_TCIF_BIT (1 << 1) /* Bit 1: Channel Transfer Complete flag */
+#define DMA_CHAN_HTIF_BIT (1 << 2) /* Bit 2: Channel Half Transfer flag */
+#define DMA_CHAN_TEIF_BIT (1 << 3) /* Bit 3: Channel Transfer Error flag */
+
+/* DMA interrupt status register */
+
+#define DMA_ISR_CHAN_SHIFT(n) DMA_CHAN_SHIFT(n)
+#define DMA_ISR_CHAN_MASK(n) (DMA_CHAN_MASK << DMA_ISR_CHAN_SHIFT(n))
+#define DMA_ISR_CHAN1_SHIFT (0) /* Bits 3-0: DMA Channel 1 interrupt status */
+#define DMA_ISR_CHAN1_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN1_SHIFT)
+#define DMA_ISR_CHAN2_SHIFT (4) /* Bits 7-4: DMA Channel 2 interrupt status */
+#define DMA_ISR_CHAN2_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN2_SHIFT)
+#define DMA_ISR_CHAN3_SHIFT (8) /* Bits 11-8: DMA Channel 3 interrupt status */
+#define DMA_ISR_CHAN3_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN3_SHIFT)
+#define DMA_ISR_CHAN4_SHIFT (12) /* Bits 15-12: DMA Channel 4 interrupt status */
+#define DMA_ISR_CHAN4_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN4_SHIFT)
+#define DMA_ISR_CHAN5_SHIFT (16) /* Bits 19-16: DMA Channel 5 interrupt status */
+#define DMA_ISR_CHAN5_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN5_SHIFT)
+#define DMA_ISR_CHAN6_SHIFT (20) /* Bits 23-20: DMA Channel 6 interrupt status */
+#define DMA_ISR_CHAN6_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN6_SHIFT)
+#define DMA_ISR_CHAN7_SHIFT (24) /* Bits 27-24: DMA Channel 7 interrupt status */
+#define DMA_ISR_CHAN7_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN7_SHIFT)
+
+#define DMA_ISR_GIF(n) (DMA_CHAN_GIF_BIT << DMA_ISR_CHAN_SHIFT(n))
+#define DMA_ISR_TCIF(n) (DMA_CHAN_TCIF_BIT << DMA_ISR_CHAN_SHIFT(n))
+#define DMA_ISR_HTIF(n) (DMA_CHAN_HTIF_BIT << DMA_ISR_CHAN_SHIFT(n))
+#define DMA_ISR_TEIF(n) (DMA_CHAN_TEIF_BIT << DMA_ISR_CHAN_SHIFT(n))
+
+/* DMA interrupt flag clear register */
+
+#define DMA_IFCR_CHAN_SHIFT(n) DMA_CHAN_SHIFT(n)
+#define DMA_IFCR_CHAN_MASK(n) (DMA_CHAN_MASK << DMA_IFCR_CHAN_SHIFT(n))
+#define DMA_IFCR_CHAN1_SHIFT (0) /* Bits 3-0: DMA Channel 1 interrupt flag clear */
+#define DMA_IFCR_CHAN1_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN1_SHIFT)
+#define DMA_IFCR_CHAN2_SHIFT (4) /* Bits 7-4: DMA Channel 2 interrupt flag clear */
+#define DMA_IFCR_CHAN2_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN2_SHIFT)
+#define DMA_IFCR_CHAN3_SHIFT (8) /* Bits 11-8: DMA Channel 3 interrupt flag clear */
+#define DMA_IFCR_CHAN3_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN3_SHIFT)
+#define DMA_IFCR_CHAN4_SHIFT (12) /* Bits 15-12: DMA Channel 4 interrupt flag clear */
+#define DMA_IFCR_CHAN4_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN4_SHIFT)
+#define DMA_IFCR_CHAN5_SHIFT (16) /* Bits 19-16: DMA Channel 5 interrupt flag clear */
+#define DMA_IFCR_CHAN5_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN5_SHIFT)
+#define DMA_IFCR_CHAN6_SHIFT (20) /* Bits 23-20: DMA Channel 6 interrupt flag clear */
+#define DMA_IFCR_CHAN6_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN6_SHIFT)
+#define DMA_IFCR_CHAN7_SHIFT (24) /* Bits 27-24: DMA Channel 7 interrupt flag clear */
+#define DMA_IFCR_CHAN7_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN7_SHIFT)
+#define DMA_IFCR_ALLCHANNELS (0x0fffffff)
+
+#define DMA_IFCR_CGIF(n) (DMA_CHAN_GIF_BIT << DMA_IFCR_CHAN_SHIFT(n))
+#define DMA_IFCR_CTCIF(n) (DMA_CHAN_TCIF_BIT << DMA_IFCR_CHAN_SHIFT(n))
+#define DMA_IFCR_CHTIF(n) (DMA_CHAN_HTIF_BIT << DMA_IFCR_CHAN_SHIFT(n))
+#define DMA_IFCR_CTEIF(n) (DMA_CHAN_TEIF_BIT << DMA_IFCR_CHAN_SHIFT(n))
+
+/* DMA channel configuration register */
+
+#define DMA_CCR_EN (1 << 0) /* Bit 0: Channel enable */
+#define DMA_CCR_TCIE (1 << 1) /* Bit 1: Transfer complete interrupt enable */
+#define DMA_CCR_HTIE (1 << 2) /* Bit 2: Half Transfer interrupt enable */
+#define DMA_CCR_TEIE (1 << 3) /* Bit 3: Transfer error interrupt enable */
+#define DMA_CCR_DIR (1 << 4) /* Bit 4: Data transfer direction */
+#define DMA_CCR_CIRC (1 << 5) /* Bit 5: Circular mode */
+#define DMA_CCR_PINC (1 << 6) /* Bit 6: Peripheral increment mode */
+#define DMA_CCR_MINC (1 << 7) /* Bit 7: Memory increment mode */
+#define DMA_CCR_PSIZE_SHIFT (8) /* Bits 8-9: Peripheral size */
+#define DMA_CCR_PSIZE_MASK (3 << DMA_CCR_PSIZE_SHIFT)
+# define DMA_CCR_PSIZE_8BITS (0 << DMA_CCR_PSIZE_SHIFT) /* 00: 8-bits */
+# define DMA_CCR_PSIZE_16BITS (1 << DMA_CCR_PSIZE_SHIFT) /* 01: 16-bits */
+# define DMA_CCR_PSIZE_32BITS (2 << DMA_CCR_PSIZE_SHIFT) /* 10: 32-bits */
+#define DMA_CCR_MSIZE_SHIFT (10) /* Bits 10-11: Memory size */
+#define DMA_CCR_MSIZE_MASK (3 << DMA_CCR_MSIZE_SHIFT)
+# define DMA_CCR_MSIZE_8BITS (0 << DMA_CCR_MSIZE_SHIFT) /* 00: 8-bits */
+# define DMA_CCR_MSIZE_16BITS (1 << DMA_CCR_MSIZE_SHIFT) /* 01: 16-bits */
+# define DMA_CCR_MSIZE_32BITS (2 << DMA_CCR_MSIZE_SHIFT) /* 10: 32-bits */
+#define DMA_CCR_PL_SHIFT (12) /* Bits 12-13: Channel Priority level */
+#define DMA_CCR_PL_MASK (3 << DMA_CCR_PL_SHIFT)
+# define DMA_CCR_PRILO (0 << DMA_CCR_PL_SHIFT) /* 00: Low */
+# define DMA_CCR_PRIMED (1 << DMA_CCR_PL_SHIFT) /* 01: Medium */
+# define DMA_CCR_PRIHI (2 << DMA_CCR_PL_SHIFT) /* 10: High */
+# define DMA_CCR_PRIVERYHI (3 << DMA_CCR_PL_SHIFT) /* 11: Very high */
+#define DMA_CCR_MEM2MEM (1 << 14) /* Bit 14: Memory to memory mode */
+
+#define DMA_CCR_ALLINTS (DMA_CCR_TEIE|DMA_CCR_HTIE|DMA_CCR_TCIE)
+
+/* DMA channel number of data register */
+
+#define DMA_CNDTR_NDT_SHIFT (0) /* Bits 15-0: Number of data to Transfer */
+#define DMA_CNDTR_NDT_MASK (0xffff << DMA_CNDTR_NDT_SHIFT)
+
+/* DMA Channel mapping. Each DMA channel has a mapping to several possible
+ * sources/sinks of data. The requests from peripherals assigned to a channel
+ * are simply OR'ed together before entering the DMA block. This means that only
+ * one request on a given channel can be enabled at once.
+ */
+
+#define STM32_DMA1_CHAN1 (0)
+#define STM32_DMA1_CHAN2 (1)
+#define STM32_DMA1_CHAN3 (2)
+#define STM32_DMA1_CHAN4 (3)
+#define STM32_DMA1_CHAN5 (4)
+#define STM32_DMA1_CHAN6 (5)
+#define STM32_DMA1_CHAN7 (6)
+
+#define STM32_DMA2_CHAN1 (7)
+#define STM32_DMA2_CHAN2 (8)
+#define STM32_DMA2_CHAN3 (1)
+#define STM32_DMA2_CHAN4 (10)
+#define STM32_DMA2_CHAN5 (11)
+
+#define DMACHAN_ADC1 STM32_DMA1_CHAN1
+#define DMACHAN_TIM2_CH3 STM32_DMA1_CHAN1
+#define DMACHAN_TIM4_CH1 STM32_DMA1_CHAN1
+#define DMACHAN_SPI1_RX STM32_DMA1_CHAN2
+#define DMACHAN_USART3_TX STM32_DMA1_CHAN2
+#define DMACHAN_TIM1_CH1 STM32_DMA1_CHAN2
+#define DMACHAN_TIM2_UP STM32_DMA1_CHAN2
+#define DMACHAN_TIM3_CH3 STM32_DMA1_CHAN2
+#define DMACHAN_SPI1_TX STM32_DMA1_CHAN3
+#define DMACHAN_USART3_RX STM32_DMA1_CHAN3
+#define DMACHAN_TIM1_CH2 STM32_DMA1_CHAN3
+#define DMACHAN_TIM3_CH4 STM32_DMA1_CHAN3
+#define DMACHAN_TIM3_UP STM32_DMA1_CHAN3
+#define DMACHAN_SPI2_RX STM32_DMA1_CHAN4
+#define DMACHAN_I2S2_RX STM32_DMA1_CHAN4
+#define DMACHAN_USART1_TX STM32_DMA1_CHAN4
+#define DMACHAN_I2C2_TX STM32_DMA1_CHAN4
+#define DMACHAN_TIM1_CH4 STM32_DMA1_CHAN4
+#define DMACHAN_TIM1_TRIG STM32_DMA1_CHAN4
+#define DMACHAN_TIM1_COM STM32_DMA1_CHAN4
+#define DMACHAN_TIM4_CH2 STM32_DMA1_CHAN4
+#define DMACHAN_SPI2_TX STM32_DMA1_CHAN5
+#define DMACHAN_I2S2_TX STM32_DMA1_CHAN5
+#define DMACHAN_USART1_RX STM32_DMA1_CHAN5
+#define DMACHAN_I2C2_RX STM32_DMA1_CHAN5
+#define DMACHAN_TIM1_UP STM32_DMA1_CHAN5
+#define DMACHAN_TIM2_CH1 STM32_DMA1_CHAN5
+#define DMACHAN_TIM4_CH3 STM32_DMA1_CHAN5
+#define DMACHAN_USART2_RX STM32_DMA1_CHAN6
+#define DMACHAN_I2C1_TX STM32_DMA1_CHAN6
+#define DMACHAN_TIM1_CH3 STM32_DMA1_CHAN6
+#define DMACHAN_TIM3_CH1 STM32_DMA1_CHAN6
+#define DMACHAN_TIM3_TRIG STM32_DMA1_CHAN6
+#define DMACHAN_USART2_TX STM32_DMA1_CHAN7
+#define DMACHAN_I2C1_RX STM32_DMA1_CHAN7
+#define DMACHAN_TIM2_CH2 STM32_DMA1_CHAN7
+#define DMACHAN_TIM2_CH4 STM32_DMA1_CHAN7
+#define DMACHAN_TIM4_UP STM32_DMA1_CHAN7
+#define DMACHAN_SPI3_RX STM32_DMA2_CHAN1
+#define DMACHAN_I2S3_RX STM32_DMA2_CHAN1
+#define DMACHAN_TIM5_CH4 STM32_DMA2_CHAN1
+#define DMACHAN_TIM5_TRIG STM32_DMA2_CHAN1
+#define DMACHAN_TIM8_CH3 STM32_DMA2_CHAN1
+#define DMACHAN_TIM8_UP STM32_DMA2_CHAN1
+#define DMACHAN_SPI3_TX STM32_DMA2_CHAN2
+#define DMACHAN_I2S3_TX STM32_DMA2_CHAN2
+#define DMACHAN_TIM5_CH3 STM32_DMA2_CHAN2
+#define DMACHAN_TIM5_UP STM32_DMA2_CHAN2
+#define DMACHAN_TIM5_UP STM32_DMA2_CHAN2
+#define DMACHAN_TIM8_TRIG STM32_DMA2_CHAN2
+#define DMACHAN_TIM8_COM STM32_DMA2_CHAN2
+#define DMACHAN_UART4_RX STM32_DMA2_CHAN3
+#define DMACHAN_TIM6_UP STM32_DMA2_CHAN3
+#define DMACHAN_DAC_CHAN1 STM32_DMA2_CHAN3
+#define DMACHAN_TIM8_CH1 STM32_DMA2_CHAN3
+#define DMACHAN_SDIO STM32_DMA2_CHAN4
+#define DMACHAN_TIM5_CH2 STM32_DMA2_CHAN4
+#define DMACHAN_TIM7_UP STM32_DMA2_CHAN4
+#define DMACHAN_DAC_CHAN2 STM32_DMA2_CHAN4
+#define DMACHAN_ADC3 STM32_DMA2_CHAN5
+#define DMACHAN_UART4_TX STM32_DMA2_CHAN5
+#define DMACHAN_TIM5_CH1 STM32_DMA2_CHAN5
+#define DMACHAN_TIM8_CH2 STM32_DMA2_CHAN5
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_DMA_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_gpio.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_gpio.h
new file mode 100644
index 000000000..e3b024129
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_gpio.h
@@ -0,0 +1,364 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f10xxx_gpio.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_CHIP_STM32F10XXX_GPIO_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_GPIO_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#define STM32_NGPIO_PORTS ((STM32_NGPIO + 15) >> 4)
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_GPIO_CRL_OFFSET 0x0000 /* Port configuration register low */
+#define STM32_GPIO_CRH_OFFSET 0x0004 /* Port configuration register high */
+#define STM32_GPIO_IDR_OFFSET 0x0008 /* Port input data register */
+#define STM32_GPIO_ODR_OFFSET 0x000c /* Port output data register */
+#define STM32_GPIO_BSRR_OFFSET 0x0010 /* Port bit set/reset register */
+#define STM32_GPIO_BRR_OFFSET 0x0014 /* Port bit reset register */
+#define STM32_GPIO_LCKR_OFFSET 0x0018 /* Port configuration lock register */
+
+#define STM32_AFIO_EVCR_OFFSET 0x0000 /* Event control register */
+#define STM32_AFIO_MAPR_OFFSET 0x0004 /* AF remap and debug I/O configuration register */
+#define STM32_AFIO_EXTICR_OFFSET(p) (0x0008 + ((p) & 0x000c)) /* Registers are displaced by 4! */
+#define STM32_AFIO_EXTICR1_OFFSET 0x0008 /* External interrupt configuration register 1 */
+#define STM32_AFIO_EXTICR2_OFFSET 0x000c /* External interrupt configuration register 2 */
+#define STM32_AFIO_EXTICR3_OFFSET 0x0010 /* External interrupt configuration register 3 */
+#define STM32_AFIO_EXTICR4_OFFSET 0x0014 /* External interrupt configuration register 4 */
+
+/* Register Addresses ***************************************************************/
+
+#if STM32_NGPIO_PORTS > 0
+# define STM32_GPIOA_CRL (STM32_GPIOA_BASE+STM32_GPIO_CRL_OFFSET)
+# define STM32_GPIOA_CRH (STM32_GPIOA_BASE+STM32_GPIO_CRH_OFFSET)
+# define STM32_GPIOA_IDR (STM32_GPIOA_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOA_ODR (STM32_GPIOA_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOA_BSRR (STM32_GPIOA_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOA_BRR (STM32_GPIOA_BASE+STM32_GPIO_BRR_OFFSET)
+# define STM32_GPIOA_LCKR (STM32_GPIOA_BASE+STM32_GPIO_LCKR_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 1
+# define STM32_GPIOB_CRL (STM32_GPIOB_BASE+STM32_GPIO_CRL_OFFSET)
+# define STM32_GPIOB_CRH (STM32_GPIOB_BASE+STM32_GPIO_CRH_OFFSET)
+# define STM32_GPIOB_IDR (STM32_GPIOB_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOB_ODR (STM32_GPIOB_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOB_BSRR (STM32_GPIOB_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOB_BRR (STM32_GPIOB_BASE+STM32_GPIO_BRR_OFFSET)
+# define STM32_GPIOB_LCKR (STM32_GPIOB_BASE+STM32_GPIO_LCKR_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 2
+# define STM32_GPIOC_CRL (STM32_GPIOC_BASE+STM32_GPIO_CRL_OFFSET)
+# define STM32_GPIOC_CRH (STM32_GPIOC_BASE+STM32_GPIO_CRH_OFFSET)
+# define STM32_GPIOC_IDR (STM32_GPIOC_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOC_ODR (STM32_GPIOC_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOC_BSRR (STM32_GPIOC_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOC_BRR (STM32_GPIOC_BASE+STM32_GPIO_BRR_OFFSET)
+# define STM32_GPIOC_LCKR (STM32_GPIOC_BASE+STM32_GPIO_LCKR_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 3
+# define STM32_GPIOD_CRL (STM32_GPIOD_BASE+STM32_GPIO_CRL_OFFSET)
+# define STM32_GPIOD_CRH (STM32_GPIOD_BASE+STM32_GPIO_CRH_OFFSET)
+# define STM32_GPIOD_IDR (STM32_GPIOD_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOD_ODR (STM32_GPIOD_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOD_BSRR (STM32_GPIOD_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOD_BRR (STM32_GPIOD_BASE+STM32_GPIO_BRR_OFFSET)
+# define STM32_GPIOD_LCKR (STM32_GPIOD_BASE+STM32_GPIO_LCKR_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 4
+# define STM32_GPIOE_CRL (STM32_GPIOE_BASE+STM32_GPIO_CRL_OFFSET)
+# define STM32_GPIOE_CRH (STM32_GPIOE_BASE+STM32_GPIO_CRH_OFFSET)
+# define STM32_GPIOE_IDR (STM32_GPIOE_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOE_ODR (STM32_GPIOE_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOE_BSRR (STM32_GPIOE_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOE_BRR (STM32_GPIOE_BASE+STM32_GPIO_BRR_OFFSET)
+# define STM32_GPIOE_LCKR (STM32_GPIOE_BASE+STM32_GPIO_LCKR_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 5
+# define STM32_GPIOF_CRL (STM32_GPIOF_BASE+STM32_GPIO_CRL_OFFSET)
+# define STM32_GPIOF_CRH (STM32_GPIOF_BASE+STM32_GPIO_CRH_OFFSET)
+# define STM32_GPIOF_IDR (STM32_GPIOF_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOF_ODR (STM32_GPIOF_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOF_BSRR (STM32_GPIOF_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOF_BRR (STM32_GPIOF_BASE+STM32_GPIO_BRR_OFFSET)
+# define STM32_GPIOF_LCKR (STM32_GPIOF_BASE+STM32_GPIO_LCKR_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 6
+# define STM32_GPIOG_CRL (STM32_GPIOG_BASE+STM32_GPIO_CRL_OFFSET)
+# define STM32_GPIOG_CRH (STM32_GPIOG_BASE+STM32_GPIO_CRH_OFFSET)
+# define STM32_GPIOG_IDR (STM32_GPIOG_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOG_ODR (STM32_GPIOG_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOG_BSRR (STM32_GPIOG_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOG_BRR (STM32_GPIOG_BASE+STM32_GPIO_BRR_OFFSET)
+# define STM32_GPIOG_LCKR (STM32_GPIOG_BASE+STM32_GPIO_LCKR_OFFSET)
+#endif
+
+#define STM32_AFIO_EVCR (STM32_AFIO_BASE+STM32_AFIO_EVCR_OFFSET)
+#define STM32_AFIO_MAPR (STM32_AFIO_BASE+STM32_AFIO_MAPR_OFFSET)
+#define STM32_AFIO_EXTICR(p) (STM32_AFIO_BASE+STM32_AFIO_EXTICR_OFFSET(p))
+#define STM32_AFIO_EXTICR1 (STM32_AFIO_BASE+STM32_AFIO_EXTICR1_OFFSET)
+#define STM32_AFIO_EXTICR2 (STM32_AFIO_BASE+STM32_AFIO_EXTICR2_OFFSET)
+#define STM32_AFIO_EXTICR3 (STM32_AFIO_BASE+STM32_AFIO_EXTICR3_OFFSET)
+#define STM32_AFIO_EXTICR4 (STM32_AFIO_BASE+STM32_AFIO_EXTICR4_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* Port configuration register low */
+
+#define GPIO_CR_MODE_SHIFT(n) ((n) << 2)
+#define GPIO_CR_MODE_MASK(n) (3 << GPIO_CR_MODE_SHIFT(n))
+#define GPIO_CR_CNF_SHIFT(n) (2 + ((n) << 2))
+#define GPIO_CR_CNF_MASK(n) (3 << GPIO_CR_CNF_SHIFT(n))
+
+#define GPIO_CR_MODECNF_SHIFT(n) ((n) << 2)
+#define GPIO_CR_MODECNF_MASK(n) (0x0f << GPIO_CR_MODECNF_SHIFT(n))
+
+#define GPIO_CRL_MODE0_SHIFT (0) /* Bits 1:0: Port mode bits */
+#define GPIO_CRL_MODE0_MASK (3 << GPIO_CRL_MODE0_SHIFT)
+#define GPIO_CRL_CNF0_SHIFT (2) /* Bits 3:2: Port configuration bits */
+#define GPIO_CRL_CNF0_MASK (3 << GPIO_CRL_CNF0_SHIFT)
+#define GPIO_CRL_MODE1_SHIFT (4) /* Bits 5:4: Port mode bits */
+#define GPIO_CRL_MODE1_MASK (3 << GPIO_CRL_MODE1_SHIFT)
+#define GPIO_CRL_CNF1_SHIFT (6) /* Bits 7:6: Port configuration bits */
+#define GPIO_CRL_CNF1_MASK (3 << GPIO_CRL_CNF1_SHIFT)
+#define GPIO_CRL_MODE2_SHIFT (8) /* Bits 9:8: Port mode bits */
+#define GPIO_CRL_MODE2_MASK (3 << GPIO_CRL_MODE2_SHIFT)
+#define GPIO_CRL_CNF2_SHIFT (10) /* Bits 11:10: Port configuration bits */
+#define GPIO_CRL_CNF2_MASK (3 << GPIO_CRL_CNF2_SHIFT)
+#define GPIO_CRL_MODE3_SHIFT (12) /* Bits 13:12: Port mode bits */
+#define GPIO_CRL_MODE3_MASK (3 << GPIO_CRL_MODE3_SHIFT)
+#define GPIO_CRL_CNF3_SHIFT (14) /* Bits 15:14: Port configuration bits */
+#define GPIO_CRL_CNF3_MASK (3 << GPIO_CRL_CNF3_SHIFT)
+#define GPIO_CRL_MODE4_SHIFT (16) /* Bits 17:16: Port mode bits */
+#define GPIO_CRL_MODE4_MASK (3 << GPIO_CRL_MODE4_SHIFT)
+#define GPIO_CRL_CNF4_SHIFT (18) /* Bits 19:18: Port configuration bits */
+#define GPIO_CRL_CNF4_MASK (3 << GPIO_CRL_CNF4_SHIFT)
+#define GPIO_CRL_MODE5_SHIFT (20) /* Bits 21:20: Port mode bits */
+#define GPIO_CRL_MODE5_MASK (3 << GPIO_CRL_MODE5_SHIFT)
+#define GPIO_CRL_CNF5_SHIFT (22) /* Bits 23:22: Port configuration bits */
+#define GPIO_CRL_CNF5_MASK (3 << GPIO_CRL_CNF5_SHIFT)
+#define GPIO_CRL_MODE6_SHIFT (24) /* Bits 25:24: Port mode bits */
+#define GPIO_CRL_MODE6_MASK (3 << GPIO_CRL_MODE6_SHIFT)
+#define GPIO_CRL_CNF6_SHIFT (26) /* Bits 27:26: Port configuration bits */
+#define GPIO_CRL_CNF6_MASK (3 << GPIO_CRL_CNF6_SHIFT)
+#define GPIO_CRL_MODE7_SHIFT (28) /* Bits 29:28: Port mode bits */
+#define GPIO_CRL_MODE7_MASK (3 << GPIO_CRL_MODE7_SHIFT)
+#define GPIO_CRL_CNF7_SHIFT (30) /* Bits 31:30: Port configuration bits */
+#define GPIO_CRL_CNF7_MASK (3 << GPIO_CRL_CNF7_SHIFT)
+
+#define GPIO_CR_CNF_INANALOG (0) /* 00: Analog input mode */
+#define GPIO_CR_CNF_INFLOAT (1) /* 01: Floating input (reset state) */
+#define GPIO_CR_CNF_INPULLUD (2) /* 10: Input with pull-up / pull-down */
+
+#define GPIO_CR_CNF_OUTPP (0) /* 00: General purpose output push-pull */
+#define GPIO_CR_CNF_OUTOD (1) /* 01: General purpose output Open-drain */
+#define GPIO_CR_CNF_ALTPP (2) /* 10: Alternate function output Push-pull */
+#define GPIO_CR_CNF_ALTOD (3) /* 11: Alternate function output Open-drain */
+
+#define GPIO_CR_MODE_INRST (0) /* 00: Input mode (reset state) */
+#define GPIO_CR_MODE_OUT10MHz (1) /* 01: Output mode, max speed 10 MHz */
+#define GPIO_CR_MODE_OUT2MHz (2) /* 10: Output mode, max speed 2 MHz */
+#define GPIO_CR_MODE_OUT50MHz (3) /* 11: Output mode, max speed 50 MHz */
+
+/* Port configuration register high */
+
+#define GPIO_CRH_MODE8_SHIFT (0) /* Bits 1:0: Port mode bits */
+#define GPIO_CRH_MODE8_MASK (3 << GPIO_CRH_MODE8_SHIFT)
+#define GPIO_CRH_CNF8_SHIFT (2) /* Bits 3:2: Port configuration bits */
+#define GPIO_CRH_CNF8_MASK (3 << GPIO_CRH_CNF8_SHIFT)
+#define GPIO_CRH_MODE9_SHIFT (4) /* Bits 5:4: Port mode bits */
+#define GPIO_CRH_MODE9_MASK (3 << GPIO_CRH_MODE9_SHIFT)
+#define GPIO_CRH_CNF9_SHIFT (6) /* Bits 7:6: Port configuration bits */
+#define GPIO_CRH_CNF9_MASK (3 << GPIO_CRH_CNF9_SHIFT)
+#define GPIO_CRH_MODE10_SHIFT (8) /* Bits 9:8: Port mode bits */
+#define GPIO_CRH_MODE10_MASK (3 << GPIO_CRH_MODE10_SHIFT)
+#define GPIO_CRH_CNF10_SHIFT (10) /* Bits 11:10: Port configuration bits */
+#define GPIO_CRH_CNF10_MASK (3 << GPIO_CRH_CNF10_SHIFT)
+#define GPIO_CRH_MODE11_SHIFT (12) /* Bits 13:12: Port mode bits */
+#define GPIO_CRH_MODE11_MASK (3 << GPIO_CRH_MODE11_SHIFT)
+#define GPIO_CRH_CNF11_SHIFT (14) /* Bits 15:14: Port configuration bits */
+#define GPIO_CRH_CNF11_MASK (3 << GPIO_CRH_CNF11_SHIFT)
+#define GPIO_CRH_MODE12_SHIFT (16) /* Bits 17:16: Port mode bits */
+#define GPIO_CRH_MODE12_MASK (3 << GPIO_CRH_MODE12_SHIFT)
+#define GPIO_CRH_CNF12_SHIFT (18) /* Bits 19:18: Port configuration bits */
+#define GPIO_CRH_CNF12_MASK (3 << GPIO_CRH_CNF12_SHIFT)
+#define GPIO_CRH_MODE13_SHIFT (20) /* Bits 21:20: Port mode bits */
+#define GPIO_CRH_MODE13_MASK (3 << GPIO_CRH_MODE13_SHIFT)
+#define GPIO_CRH_CNF13_SHIFT (22) /* Bits 23:22: Port configuration bits */
+#define GPIO_CRH_CNF13_MASK (3 << GPIO_CRH_CNF13_SHIFT)
+#define GPIO_CRH_MODE14_SHIFT (24) /* Bits 25:24: Port mode bits */
+#define GPIO_CRH_MODE14_MASK (3 << GPIO_CRH_MODE14_SHIFT)
+#define GPIO_CRH_CNF14_SHIFT (26) /* Bits 27:26: Port configuration bits */
+#define GPIO_CRH_CNF14_MASK (3 << GPIO_CRH_CNF14_SHIFT)
+#define GPIO_CRH_MODE15_SHIFT (28) /* Bits 29:28: Port mode bits */
+#define GPIO_CRH_MODE15_MASK (3 << GPIO_CRH_MODE15_SHIFT)
+#define GPIO_CRH_CNF15_SHIFT (30) /* Bits 31:30: Port configuration bits */
+#define GPIO_CRL_CNF15_MASK (3 << GPIO_CRL_CNF15_SHIFT)
+
+/* Port input/ouput data register */
+
+#define GPIO_IDR(n) (1 << (n))
+#define GPIO_ODR(n) (1 << (n))
+
+/* Port bit set/reset register */
+
+#define GPIO_BSRR_RESET(n) (1 << ((n)+16))
+#define GPIO_BSRR_SET(n) (1 << (n))
+#define GPIO_BRR(n) (1 << (n))
+
+/* Port configuration lock register */
+
+#define GPIO_LCKR_LCKK (1 << 16) /* Bit 16: Lock key */
+#define GPIO_LCKR_LCK(n) (1 << (n))
+
+/* Event control register */
+
+#define AFIO_EVCR_PIN_SHIFT (0) /* Bits 3-0: Pin selection */
+#define AFIO_EVCR_PIN_MASK (0x0f << AFIO_EVCR_PIN_SHIFT)
+#define AFIO_EVCR_PORT_SHIFT (4) /* Bits 6-4: Port selection */
+#define AFIO_EVCR_PORT_MASK (7 << AFIO_EVCR_PORT_SHIFT)
+# define AFIO_EVCR_PORTA (0 << AFIO_EVCR_PORT_SHIFT) /* 000: PA selected */
+# define AFIO_EVCR_PORTB (1 << AFIO_EVCR_PORT_SHIFT) /* 001: PB selected */
+# define AFIO_EVCR_PORTC (2 << AFIO_EVCR_PORT_SHIFT) /* 010: PC selected */
+# define AFIO_EVCR_PORTD (3 << AFIO_EVCR_PORT_SHIFT) /* 011: PD selected */
+# define AFIO_EVCR_PORTE (4 << AFIO_EVCR_PORT_SHIFT) /* 100: PE selected */
+#define AFIO_EVCR_EVOE (1 << 7) /* Bit 7: Event Output Enable */
+
+/* AF remap and debug I/O configuration register */
+
+#define AFIO_MAPR_SWJ_CFG_SHIFT (24) /* Bits 26-24: Serial Wire JTAG configuration*/
+#define AFIO_MAPR_SWJ_CFG_MASK (7 << AFIO_MAPR_SWJ_CFG_SHIFT)
+# define AFIO_MAPR_SWJRST (0 << AFIO_MAPR_SWJ_CFG_SHIFT) /* 000: Full SWJ (JTAG-DP + SW-DP): Reset State */
+# define AFIO_MAPR_SWJ (1 << AFIO_MAPR_SWJ_CFG_SHIFT) /* 001: Full SWJ (JTAG-DP + SW-DP) but without JNTRST */
+# define AFIO_MAPR_SWDP (2 << AFIO_MAPR_SWJ_CFG_SHIFT) /* 010: JTAG-DP Disabled and SW-DP Enabled */
+# define AFIO_MAPR_DISAB (4 << AFIO_MAPR_SWJ_CFG_SHIFT) /* 100: JTAG-DP Disabled and SW-DP Disabled */
+#define AFIO_MAPR_PD01_REMAP (1 << 15) /* Bit 15 : Port D0/Port D1 mapping on OSC_IN/OSC_OUT */
+#define AFIO_MAPR_CAN_REMAP_SHIFT (13) /* Bits 14-13: CAN Alternate function remapping */
+#define AFIO_MAPR_CAN_REMAP_MASK (3 << AFIO_MAPR_CAN_REMAP_SHIFT)
+# define AFIO_MAPR_PA1112 (0 << AFIO_MAPR_CAN_REMAP_SHIFT) /* 00: CANRX mapped to PA11, CANTX mapped to PA12 */
+# define AFIO_MAPR_PB89 (2 << AFIO_MAPR_CAN_REMAP_SHIFT) /* 10: CANRX mapped to PB8, CANTX mapped to PB9 */
+# define AFIO_MAPR_PD01 (3 << AFIO_MAPR_CAN_REMAP_SHIFT) /* 11: CANRX mapped to PD0, CANTX mapped to PD1 */
+#define AFIO_MAPR_TIM4_REMAP (1 << 12) /* Bit 12: TIM4 remapping */
+#define AFIO_MAPR_TIM3_REMAP_SHIFT (10) /* Bits 11-10: TIM3 remapping */
+#define AFIO_MAPR_TIM3_REMAP_MASK (3 << AFIO_MAPR_TIM3_REMAP_SHIFT)
+# define AFIO_MAPR_TIM3_NOREMAP (0 << AFIO_MAPR_TIM3_REMAP_SHIFT) /* 00: No remap (CH1/PA6, CH2/PA7, CH3/PB0, CH4/PB1) */
+# define AFIO_MAPR_TIM3_PARTREMAP (2 << AFIO_MAPR_TIM3_REMAP_SHIFT) /* 10: Partial remap (CH1/PB4, CH2/PB5, CH3/PB0, CH4/PB1) */
+# define AFIO_MAPR_TIM3_FULLREMAP (3 << AFIO_MAPR_TIM3_REMAP_SHIFT) /* 11: Full remap (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9) */
+#define AFIO_MAPR_TIM2_REMAP_SHIFT (8) /* Bits 9-8: TIM2 remapping */
+#define AFIO_MAPR_TIM2_REMAP_MASK (3 << AFIO_MAPR_TIM2_REMAP_SHIFT)
+# define AFIO_MAPR_TIM2_NOREMAP (0 << AFIO_MAPR_TIM2_REMAP_SHIFT) /* 00: No remap (CH1/ETR/PA0, CH2/PA1, CH3/PA2, CH4/PA3) */
+# define AFIO_MAPR_TIM2_PARTREMAP1 (1 << AFIO_MAPR_TIM2_REMAP_SHIFT) /* 01: Partial remap (CH1/ETR/PA15, CH2/PB3, CH3/PA2, CH4/PA3) */
+# define AFIO_MAPR_TIM2_PARTREMAP2 (2 << AFIO_MAPR_TIM2_REMAP_SHIFT) /* 10: Partial remap (CH1/ETR/PA0, CH2/PA1, CH3/PB10, CH4/PB11) */
+# define AFIO_MAPR_TIM2_FULLREMAP (3 << AFIO_MAPR_TIM2_REMAP_SHIFT) /* 11: Full remap (CH1/ETR/PA15, CH2/PB3, CH3/PB10, CH4/PB11) */
+#define AFIO_MAPR_TIM1_REMAP_SHIFT (6) /* Bits 7-6: TIM1 remapping */
+#define AFIO_MAPR_TIM1_REMAP_MASK (3 << AFIO_MAPR_TIM1_REMAP_SHIFT)
+# define AFIO_MAPR_TIM1_NOREMAP (0 << AFIO_MAPR_TIM1_REMAP_SHIFT) /* 00: No remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PB12, CH1N/PB13, CH2N/PB14, CH3N/PB15) */
+# define AFIO_MAPR_TIM1_PARTREMAP (1 << AFIO_MAPR_TIM1_REMAP_SHIFT) /* 01: Partial remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PA6, CH1N/PA7, CH2N/PB0, CH3N/PB1) */
+# define AFIO_MAPR_TIM1_FULLREMAP (3 << AFIO_MAPR_TIM1_REMAP_SHIFT) /* 11: Full remap (ETR/PE7, CH1/PE9, CH2/PE11, CH3/PE13, CH4/PE14, BKIN/PE15, CH1N/PE8, CH2N/PE10, CH3N/PE12) */
+#define AFIO_MAPR_USART3_REMAP_SHIFT (6) /* Bits 5-4: USART3 remapping */
+#define AFIO_MAPR_USART3_REMAP_MASK (3 << AFIO_MAPR_USART3_REMAP_SHIFT)
+# define AFIO_MAPR_USART3_NOREMAP (0 << AFIO_MAPR_USART3_REMAP_SHIFT) /* 00: No remap (TX/PB10, RX/PB11, CK/PB12, CTS/PB13, RTS/PB14) */
+# define AFIO_MAPR_USART3_PARTREMAP (1 << AFIO_MAPR_USART3_REMAP_SHIFT) /* 01: Partial remap (TX/PC10, RX/PC11, CK/PC12, CTS/PB13, RTS/PB14) */
+# define AFIO_MAPR_USART3_FULLREMAP (3 << AFIO_MAPR_USART3_REMAP_SHIFT) /* 11: Full remap (TX/PD8, RX/PD9, CK/PD10, CTS/PD11, RTS/PD12) */
+#define AFIO_MAPR_USART2_REMAP (1 << 3) /* Bit 3: USART2 remapping */
+#define AFIO_MAPR_USART1_REMAP (1 << 2) /* Bit 2: USART1 remapping */
+#define AFIO_MAPR_I2C1_REMAP (1 << 1) /* Bit 1: I2C1 remapping */
+#define AFIO_MAPR_SPI1_REMAP (1 << 0) /* Bit 0: SPI1 remapping */
+
+/* External interrupt configuration register 1 */
+
+#define AFIO_EXTICR_PORT_MASK (0x0f)
+#define AFIO_EXTICR_EXTI_SHIFT(g) (((g) & 3) << 2)
+#define AFIO_EXTICR_EXTI_MASK(g) (AFIO_EXTICR_PORT_MASK << (AFIO_EXTICR_EXTI_SHIFT(g)))
+
+#define AFIO_EXTICR1_EXTI0_SHIFT (0) /* Bits 3-0: EXTI 0 configuration */
+#define AFIO_EXTICR1_EXTI0_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR1_EXTI0_SHIFT)
+#define AFIO_EXTICR1_EXTI1_SHIFT (4) /* Bits 7-4: EXTI 1 configuration */
+#define AFIO_EXTICR1_EXTI1_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR1_EXTI1_SHIFT)
+#define AFIO_EXTICR1_EXTI2_SHIFT (8) /* Bits 11-8: EXTI 2 configuration */
+#define AFIO_EXTICR1_EXTI2_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR1_EXTI2_SHIFT)
+#define AFIO_EXTICR1_EXTI3_SHIFT (12) /* Bits 15-12: EXTI 3 configuration */
+#define AFIO_EXTICR1_EXTI3_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR1_EXTI3_SHIFT)
+
+#define AFIO_EXTICR_PORTA (0) /* 0000: PA[x] pin */
+#define AFIO_EXTICR_PORTB (1) /* 0001: PB[x] pin */
+#define AFIO_EXTICR_PORTC (2) /* 0010: PC[x] pin */
+#define AFIO_EXTICR_PORTD (3) /* 0011: PD[x] pin */
+#define AFIO_EXTICR_PORTE (4) /* 0100: PE[x] pin */
+#define AFIO_EXTICR_PORTF (5) /* 0101: PF[x] pin */
+#define AFIO_EXTICR_PORTG (6) /* 0110: PG[x] pin */
+
+/* External interrupt configuration register 2 */
+
+#define AFIO_EXTICR2_EXTI4_SHIFT (0) /* Bits 3-0: EXTI 4 configuration */
+#define AFIO_EXTICR2_EXTI4_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR2_EXTI4_SHIFT)
+#define AFIO_EXTICR2_EXTI5_SHIFT (4) /* Bits 7-4: EXTI 5 configuration */
+#define AFIO_EXTICR2_EXTI5_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR2_EXTI5_SHIFT)
+#define AFIO_EXTICR2_EXTI6_SHIFT (8) /* Bits 11-8: EXTI 6 configuration */
+#define AFIO_EXTICR2_EXTI6_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR2_EXTI6_SHIFT)
+#define AFIO_EXTICR2_EXTI7_SHIFT (12) /* Bits 15-12: EXTI 7 configuration */
+#define AFIO_EXTICR2_EXTI7_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR2_EXTI7_SHIFT)
+
+/* External interrupt configuration register 3 */
+
+#define AFIO_EXTICR3_EXTI8_SHIFT (0) /* Bits 3-0: EXTI 8 configuration */
+#define AFIO_EXTICR3_EXTI8_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR3_EXTI8_SHIFT)
+#define AFIO_EXTICR3_EXTI9_SHIFT (4) /* Bits 7-4: EXTI 9 configuration */
+#define AFIO_EXTICR3_EXTI9_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR3_EXTI9_SHIFT)
+#define AFIO_EXTICR3_EXTI10_SHIFT (8) /* Bits 11-8: EXTI 10 configuration */
+#define AFIO_EXTICR3_EXTI10_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR3_EXTI10_SHIFT)
+#define AFIO_EXTICR3_EXTI11_SHIFT (12) /* Bits 15-12: EXTI 11 configuration */
+#define AFIO_EXTICR3_EXTI11_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR3_EXTI11_SHIFT)
+
+/* External interrupt configuration register 4 */
+
+#define AFIO_EXTICR4_EXTI12_SHIFT (0) /* Bits 3-0: EXTI 12 configuration */
+#define AFIO_EXTICR4_EXTI12_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR4_EXTI12_SHIFT)
+#define AFIO_EXTICR4_EXTI13_SHIFT (4) /* Bits 7-4: EXTI 13 configuration */
+#define AFIO_EXTICR4_EXTI13_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR4_EXTI13_SHIFT)
+#define AFIO_EXTICR4_EXTI14_SHIFT (8) /* Bits 11-8: EXTI 14 configuration */
+#define AFIO_EXTICR4_EXTI14_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR4_EXTI14_SHIFT)
+#define AFIO_EXTICR4_EXTI15_SHIFT (12) /* Bits 15-12: EXTI 15 configuration */
+#define AFIO_EXTICR4_EXTI15_MASK (AFIO_EXTICR_PORT_MASK << AFIO_EXTICR4_EXTI15_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_GPIO_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_memorymap.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_memorymap.h
new file mode 100644
index 000000000..80b38a89f
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_memorymap.h
@@ -0,0 +1,136 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f10xxx_memorymap.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_CHIP_STM32F10XXX_MEMORYMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_MEMORYMAP_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* FLASH and SRAM *******************************************************************/
+
+#define STM32_FLASH_BASE 0x08000000 /* 0x08000000 - Up to 512Kb */
+#define STM32_SRAM_BASE 0x20000000 /* 0x20000000 - 64Kb SRAM */
+#define STM32_SRAMBB_BASE 0x22000000
+#define STM32_PERIPH_BASE 0x40000000
+
+/* Register Base Address ************************************************************/
+
+/* APB1 bus */
+
+#define STM32_TIM2_BASE 0x40000000 /* 0x40000000 - 0x400003ff: TIM2 timer */
+#define STM32_TIM3_BASE 0x40000400 /* 0x40000400 - 0x400007ff: TIM3 timer */
+#define STM32_TIM4_BASE 0x40000800 /* 0x40000800 - 0x40000bff: TIM4 timer */
+#define STM32_TIM5_BASE 0x40000c00 /* 0x40000c00 - 0x40000fff: TIM5 timer */
+#define STM32_TIM6_BASE 0x40001000 /* 0x40001000 - 0x400013ff: TIM6 timer */
+#define STM32_TIM7_BASE 0x40001400 /* 0x40001400 - 0x400007ff: TIM7 timer */
+ /* 0x40001800 - 0x40000fff: Reserved */
+#define STM32_RTC_BASE 0x40002800 /* 0x40002800 - 0x40002bff: RTC */
+#define STM32_WWDG_BASE 0x40002c00 /* 0x40002C00 - 0x40002fff: Window watchdog (WWDG) */
+#define STM32_IWDG_BASE 0x40003000 /* 0x40003000 - 0x400033ff: Independent watchdog (IWDG) */
+ /* 0x40003400 - 0x400037ff: Reserved */
+#define STM32_SPI2_BASE 0x40003800 /* 0x40003800 - 0x40003bff: SPI2/I2S2 */
+#define STM32_I2S2_BASE 0x40003800
+#define STM32_SPI3_BASE 0x40003c00 /* 0x40003c00 - 0x40003fff: SPI3/I2S3 */
+#define STM32_I2S3_BASE 0x40003c00
+ /* 0x40004000 - 0x400043ff: Reserved */
+#define STM32_USART2_BASE 0x40004400 /* 0x40004400 - 0x400047ff: USART2 */
+#define STM32_USART3_BASE 0x40004800 /* 0x40004800 - 0x40004bff: USART3 */
+#define STM32_UART4_BASE 0x40004c00 /* 0x40004c00 - 0x40004fff: UART4 */
+#define STM32_UART5_BASE 0x40005000 /* 0x40005000 - 0x400053ff: UART5 */
+#define STM32_I2C1_BASE 0x40005400 /* 0x40005400 - 0x400057ff: I2C1 */
+#define STM32_I2C2_BASE 0x40005800 /* 0x40005800 - 0x40005Bff: I2C2 */
+#define STM32_USB_BASE 0x40005c00 /* 0x40005c00 - 0x40005fff: USB device FS registers */
+#define STM32_USBCANRAM_BASE 0x40006000 /* 0x40006000 - 0x400063ff: Shared USB/CAN SRAM 512 bytes */
+#define STM32_CAN1_BASE 0x40006400 /* 0x40006400 - 0x400067ff: bxCAN1 */
+#define STM32_CAN2_BASE 0x40006800 /* 0x40006800 - 0x40006bff: bxCAN2 */
+#define STM32_BKP_BASE 0x40006c00 /* 0x40006c00 - 0x40006fff: Backup registers (BKP) */
+#define STM32_PWR_BASE 0x40007000 /* 0x40007000 - 0x400073ff: Power control PWR */
+#define STM32_DAC_BASE 0x40007400 /* 0x40007400 - 0x400077ff: DAC */
+ /* 0x40007800 - 0x4000ffff: Reserved */
+
+/* APB2 bus */
+
+#define STM32_AFIO_BASE 0x40010000 /* 0x40010000 - 0x400103ff: AFIO */
+#define STM32_EXTI_BASE 0x40010400 /* 0x40010400 - 0x400107ff: EXTI */
+#define STM32_GPIOA_BASE 0x40010800 /* 0x40010800 - 0x40010bff: GPIO Port A */
+#define STM32_GPIOB_BASE 0X40010c00 /* 0X40010c00 - 0x40010fff: GPIO Port B */
+#define STM32_GPIOC_BASE 0x40011000 /* 0x40011000 - 0x400113ff: GPIO Port C */
+#define STM32_GPIOD_BASE 0x40011400 /* 0x40011400 - 0x400117ff: GPIO Port D */
+#define STM32_GPIOE_BASE 0x40011800 /* 0x40011800 - 0x40011bff: GPIO Port E */
+#define STM32_GPIOF_BASE 0x40011c00 /* 0x4001c000 - 0x400111ff: GPIO Port F */
+#define STM32_GPIOG_BASE 0x40012000 /* 0x40012000 - 0x400123ff: GPIO Port G */
+#define STM32_ADC1_BASE 0x40012400 /* 0x40012400 - 0x400127ff: ADC1 */
+#define STM32_ADC2_BASE 0x40012800 /* 0x40012800 - 0x40012bff: ADC2 */
+#define STM32_TIM1_BASE 0x40012c00 /* 0x40012c00 - 0x40012fff: TIM1 timer */
+#define STM32_SPI1_BASE 0x40013000 /* 0x40013000 - 0x400133ff: SPI1 */
+#define STM32_TIM8_BASE 0x40013400 /* 0x40013400 - 0x400137ff: TIM8 timer */
+#define STM32_USART1_BASE 0x40013800 /* 0x40013800 - 0x40013bff: USART1 */
+#define STM32_ADC3_BASE 0x40012800 /* 0x40012800 - 0x40013fff: ADC3 */
+ /* 0x40014000 - 0x40017fff: Reserved */
+/* AHB bus */
+
+#define STM32_SDIO_BASE 0x40018000 /* 0x40018000 - 0x400183ff: SDIO */
+ /* 0x40018400 - 0x40017fff: Reserved */
+#define STM32_DMA1_BASE 0x40020000 /* 0x40020000 - 0x400203ff: DMA1 */
+#define STM32_DMA2_BASE 0x40020400 /* 0x40020000 - 0x400207ff: DMA2 */
+ /* 0x40020800 - 0x40020fff: Reserved */
+#define STM32_RCC_BASE 0x40021000 /* 0x40021000 - 0x400213ff: Reset and Clock control RCC */
+ /* 0x40021400 - 0x40021fff: Reserved */
+#define STM32_OTGFS_BASE 0x50000000 /* 0x50000000 - 0x500003ff: USB OTG FS */
+#define STM32_FLASHIF_BASE 0x40022000 /* 0x40022000 - 0x400223ff: Flash memory interface */
+#define STM32_CRC_BASE 0x40028000 /* 0x40023000 - 0x400233ff: CRC */
+ /* 0x40023400 - 0x40027fff: Reserved */
+#define STM32_ETHERNET_BASE 0x40028000 /* 0x40028000 - 0x40029fff: Ethernet */
+ /* 0x40030000 - 0x4fffffff: Reserved */
+
+/* Peripheral BB base */
+
+#define STM32_PERIPHBB_BASE 0x42000000
+
+/* Flexible SRAM controller (FSMC) */
+
+#define STM32_FSMC_BASE 0xa0000000
+
+/* Other registers -- see armv7-m/nvic.h for standard Cortex-M3 registers in this
+ * address range
+ */
+
+#define STM32_SCS_BASE 0xe000e000
+#define STM32_DEBUGMCU_BASE 0xe0042000
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_MEMORYMAP_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rcc.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rcc.h
new file mode 100644
index 000000000..31544c99f
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rcc.h
@@ -0,0 +1,328 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f10xx_rcc.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_CHIP_STM32F10XXX_RCC_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RCC_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_RCC_CR_OFFSET 0x0000 /* Clock control register */
+#define STM32_RCC_CFGR_OFFSET 0x0004 /* Clock configuration register */
+#define STM32_RCC_CIR_OFFSET 0x0008 /* Clock interrupt register */
+#define STM32_RCC_APB2RSTR_OFFSET 0x000c /* APB2 Peripheral reset register */
+#define STM32_RCC_APB1RSTR_OFFSET 0x0010 /* APB1 Peripheral reset register */
+#define STM32_RCC_AHBENR_OFFSET 0x0014 /* AHB Peripheral Clock enable register */
+#define STM32_RCC_APB2ENR_OFFSET 0x0018 /* APB2 Peripheral Clock enable register */
+#define STM32_RCC_APB1ENR_OFFSET 0x001c /* APB1 Peripheral Clock enable register */
+#define STM32_RCC_BDCR_OFFSET 0x0020 /* Backup domain control register */
+#define STM32_RCC_CSR_OFFSET 0x0024 /* Control/status register */
+#ifdef CONFIG_STM32_VALUELINE
+# define STM32_RCC_CFGR2_OFFSET 0x002c /* Clock configuration register 2 */
+#endif
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_RCC_CR (STM32_RCC_BASE+STM32_RCC_CR_OFFSET)
+#define STM32_RCC_CFGR (STM32_RCC_BASE+STM32_RCC_CFGR_OFFSET)
+#define STM32_RCC_CIR (STM32_RCC_BASE+STM32_RCC_CIR_OFFSET)
+#define STM32_RCC_APB2RSTR (STM32_RCC_BASE+STM32_RCC_APB2RSTR_OFFSET)
+#define STM32_RCC_APB1RSTR (STM32_RCC_BASE+STM32_RCC_APB1RSTR_OFFSET)
+#define STM32_RCC_AHBENR (STM32_RCC_BASE+STM32_RCC_AHBENR_OFFSET)
+#define STM32_RCC_APB2ENR (STM32_RCC_BASE+STM32_RCC_APB2ENR_OFFSET)
+#define STM32_RCC_APB1ENR (STM32_RCC_BASE+STM32_RCC_APB1ENR_OFFSET)
+#define STM32_RCC_BDCR (STM32_RCC_BASE+STM32_RCC_BDCR_OFFSET)
+#define STM32_RCC_CSR (STM32_RCC_BASE+STM32_RCC_CSR_OFFSET)
+#ifdef CONFIG_STM32_VALUELINE
+# define STM32_RCC_CFGR2 (STM32_RCC_BASE+STM32_RCC_CFGR2_OFFSET)
+#endif
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* Clock control register */
+
+#define RCC_CR_HSION (1 << 0) /* Bit 0: Internal High Speed clock enable */
+#define RCC_CR_HSIRDY (1 << 1) /* Bit 1: Internal High Speed clock ready flag */
+#define RCC_CR_HSITRIM_SHIFT (3) /* Bits 7-3: Internal High Speed clock trimming */
+#define RCC_CR_HSITRIM_MASK (0x1f << RCC_CR_HSITRIM_SHIFT)
+#define RCC_CR_HSICAL_SHIFT (8) /* Bits 15-8: Internal High Speed clock Calibration */
+#define RCC_CR_HSICAL_MASK (0xff << RCC_CR_HSICAL_SHIFT)
+#define RCC_CR_HSEON (1 << 16) /* Bit 16: External High Speed clock enable */
+#define RCC_CR_HSERDY (1 << 17) /* Bit 17: External High Speed clock ready flag */
+#define RCC_CR_HSEBYP (1 << 18) /* Bit 18: External High Speed clock Bypass */
+#define RCC_CR_CSSON (1 << 19) /* Bit 19: Clock Security System enable */
+#define RCC_CR_PLLON (1 << 24) /* Bit 24: PLL enable */
+#define RCC_CR_PLLRDY (1 << 25) /* Bit 25: PLL clock ready flag */
+
+/* Clock configuration register */
+
+#define RCC_CFGR_SW_SHIFT (0) /* Bits 1-0: System clock Switch */
+#define RCC_CFGR_SW_MASK (3 << RCC_CFGR_SW_SHIFT)
+# define RCC_CFGR_SW_HSI (0 << RCC_CFGR_SW_SHIFT) /* 00: HSI selected as system clock */
+# define RCC_CFGR_SW_HSE (1 << RCC_CFGR_SW_SHIFT) /* 01: HSE selected as system clock */
+# define RCC_CFGR_SW_PLL (2 << RCC_CFGR_SW_SHIFT) /* 10: PLL selected as system clock */
+#define RCC_CFGR_SWS_SHIFT (2) /* Bits 3-2: System Clock Switch Status */
+#define RCC_CFGR_SWS_MASK (3 << RCC_CFGR_SWS_SHIFT)
+# define RCC_CFGR_SWS_HSI (0 << RCC_CFGR_SWS_SHIFT) /* 00: HSI oscillator used as system clock */
+# define RCC_CFGR_SWS_HSE (1 << RCC_CFGR_SWS_SHIFT) /* 01: HSE oscillator used as system clock */
+# define RCC_CFGR_SWS_PLL (2 << RCC_CFGR_SWS_SHIFT) /* 10: PLL used as system clock */
+#define RCC_CFGR_HPRE_SHIFT (4) /* Bits 7-4: AHB prescaler */
+#define RCC_CFGR_HPRE_MASK (0x0f << RCC_CFGR_HPRE_SHIFT)
+# define RCC_CFGR_HPRE_SYSCLK (0 << RCC_CFGR_HPRE_SHIFT) /* 0xxx: SYSCLK not divided */
+# define RCC_CFGR_HPRE_SYSCLKd2 (8 << RCC_CFGR_HPRE_SHIFT) /* 1000: SYSCLK divided by 2 */
+# define RCC_CFGR_HPRE_SYSCLKd4 (9 << RCC_CFGR_HPRE_SHIFT) /* 1001: SYSCLK divided by 4 */
+# define RCC_CFGR_HPRE_SYSCLKd8 (10 << RCC_CFGR_HPRE_SHIFT) /* 1010: SYSCLK divided by 8 */
+# define RCC_CFGR_HPRE_SYSCLKd16 (11 << RCC_CFGR_HPRE_SHIFT) /* 1011: SYSCLK divided by 16 */
+# define RCC_CFGR_HPRE_SYSCLKd64 (12 << RCC_CFGR_HPRE_SHIFT) /* 1100: SYSCLK divided by 64 */
+# define RCC_CFGR_HPRE_SYSCLKd128 (13 << RCC_CFGR_HPRE_SHIFT) /* 1101: SYSCLK divided by 128 */
+# define RCC_CFGR_HPRE_SYSCLKd256 (14 << RCC_CFGR_HPRE_SHIFT) /* 1110: SYSCLK divided by 256 */
+# define RCC_CFGR_HPRE_SYSCLKd512 (15 << RCC_CFGR_HPRE_SHIFT) /* 1111: SYSCLK divided by 512 */
+#define RCC_CFGR_PPRE1_SHIFT (8) /* Bits 10-8: APB Low speed prescaler (APB1) */
+#define RCC_CFGR_PPRE1_MASK (7 << RCC_CFGR_PPRE1_SHIFT)
+# define RCC_CFGR_PPRE1_HCLK (0 << RCC_CFGR_PPRE1_SHIFT) /* 0xx: HCLK not divided */
+# define RCC_CFGR_PPRE1_HCLKd2 (4 << RCC_CFGR_PPRE1_SHIFT) /* 100: HCLK divided by 2 */
+# define RCC_CFGR_PPRE1_HCLKd4 (5 << RCC_CFGR_PPRE1_SHIFT) /* 101: HCLK divided by 4 */
+# define RCC_CFGR_PPRE1_HCLKd8 (6 << RCC_CFGR_PPRE1_SHIFT) /* 110: HCLK divided by 8 */
+# define RCC_CFGR_PPRE1_HCLKd16 (7 << RCC_CFGR_PPRE1_SHIFT) /* 111: HCLK divided by 16 */
+#define RCC_CFGR_PPRE2_SHIFT (11) /* Bits 13-11: APB High speed prescaler (APB2) */
+#define RCC_CFGR_PPRE2_MASK (7 << RCC_CFGR_PPRE2_SHIFT)
+# define RCC_CFGR_PPRE2_HCLK (0 << RCC_CFGR_PPRE2_SHIFT) /* 0xx: HCLK not divided */
+# define RCC_CFGR_PPRE2_HCLKd2 (4 << RCC_CFGR_PPRE2_SHIFT) /* 100: HCLK divided by 2 */
+# define RCC_CFGR_PPRE2_HCLKd4 (5 << RCC_CFGR_PPRE2_SHIFT) /* 101: HCLK divided by 4 */
+# define RCC_CFGR_PPRE2_HCLKd8 (6 << RCC_CFGR_PPRE2_SHIFT) /* 110: HCLK divided by 8 */
+# define RCC_CFGR_PPRE2_HCLKd16 (7 << RCC_CFGR_PPRE2_SHIFT) /* 111: HCLK divided by 16 */
+#define RCC_CFGR_ADCPRE_SHIFT (14) /* Bits 15-14: ADC prescaler */
+#define RCC_CFGR_ADCPRE_MASK (3 << RCC_CFGR_ADCPRE_SHIFT)
+# define RCC_CFGR_PLCK2d2 (0 << RCC_CFGR_ADCPRE_SHIFT) /* 00: PLCK2 divided by 2 */
+# define RCC_CFGR_PLCK2d4 (1 << RCC_CFGR_ADCPRE_SHIFT) /* 01: PLCK2 divided by 4 */
+# define RCC_CFGR_PLCK2d6 (2 << RCC_CFGR_ADCPRE_SHIFT) /* 10: PLCK2 divided by 6 */
+# define RCC_CFGR_PLCK2d8 (3 << RCC_CFGR_ADCPRE_SHIFT) /* 11: PLCK2 divided by 8 */
+#define RCC_CFGR_PLLSRC (1 << 16) /* Bit 16: PLL entry clock source */
+#define RCC_CFGR_PLLXTPRE (1 << 17) /* Bit 17: HSE divider for PLL entry */
+#define RCC_CFGR_PLLMUL_SHIFT (18) /* Bits 21-18: PLL Multiplication Factor */
+#define RCC_CFGR_PLLMUL_MASK (0x0f << RCC_CFGR_PLLMUL_SHIFT)
+# define RCC_CFGR_PLLMUL_CLKx2 (0 << RCC_CFGR_PLLMUL_SHIFT) /* 0000: PLL input clock x 2 */
+# define RCC_CFGR_PLLMUL_CLKx3 (1 << RCC_CFGR_PLLMUL_SHIFT) /* 0001: PLL input clock x 3 */
+# define RCC_CFGR_PLLMUL_CLKx4 (2 << RCC_CFGR_PLLMUL_SHIFT) /* 0010: PLL input clock x 4 */
+# define RCC_CFGR_PLLMUL_CLKx5 (3 << RCC_CFGR_PLLMUL_SHIFT) /* 0011: PLL input clock x 5 */
+# define RCC_CFGR_PLLMUL_CLKx6 (4 << RCC_CFGR_PLLMUL_SHIFT) /* 0100: PLL input clock x 6 */
+# define RCC_CFGR_PLLMUL_CLKx7 (5 << RCC_CFGR_PLLMUL_SHIFT) /* 0101: PLL input clock x 7 */
+# define RCC_CFGR_PLLMUL_CLKx8 (6 << RCC_CFGR_PLLMUL_SHIFT) /* 0110: PLL input clock x 8 */
+# define RCC_CFGR_PLLMUL_CLKx9 (7 << RCC_CFGR_PLLMUL_SHIFT) /* 0111: PLL input clock x 9 */
+# define RCC_CFGR_PLLMUL_CLKx10 (8 << RCC_CFGR_PLLMUL_SHIFT) /* 1000: PLL input clock x 10 */
+# define RCC_CFGR_PLLMUL_CLKx11 (9 << RCC_CFGR_PLLMUL_SHIFT) /* 1001: PLL input clock x 11 */
+# define RCC_CFGR_PLLMUL_CLKx12 (10 << RCC_CFGR_PLLMUL_SHIFT) /* 1010: PLL input clock x 12 */
+# define RCC_CFGR_PLLMUL_CLKx13 (11 << RCC_CFGR_PLLMUL_SHIFT) /* 1011: PLL input clock x 13 */
+# define RCC_CFGR_PLLMUL_CLKx14 (12 << RCC_CFGR_PLLMUL_SHIFT) /* 1100: PLL input clock x 14 */
+# define RCC_CFGR_PLLMUL_CLKx15 (13 << RCC_CFGR_PLLMUL_SHIFT) /* 1101: PLL input clock x 15 */
+# define RCC_CFGR_PLLMUL_CLKx16 (14 << RCC_CFGR_PLLMUL_SHIFT) /* 111x: PLL input clock x 16 */
+#define RCC_CFGR_USBPRE (1 << 22) /* Bit 22: USB prescaler */
+#define RCC_CFGR_MCO_SHIFT (24) /* Bits 26-24: Microcontroller Clock Output */
+#define RCC_CFGR_MCO_MASK (7 << RCC_CFGR_MCO_SHIFT)
+# define RCC_CFGR_NOCLK (0 << RCC_CFGR_MCO_SHIFT) /* 0xx: No clock */
+# define RCC_CFGR_SYSCLK (4 << RCC_CFGR_MCO_SHIFT) /* 100: System clock selected */
+# define RCC_CFGR_INTCLK (5 << RCC_CFGR_MCO_SHIFT) /* 101: Internal 8 MHz RC oscillator clock selected */
+# define RCC_CFGR_EXTCLK (6 << RCC_CFGR_MCO_SHIFT) /* 110: External 1-25 MHz oscillator clock selected */
+# define RCC_CFGR_PLLCLKd2 (7 << RCC_CFGR_MCO_SHIFT) /* 111: PLL clock divided by 2 selected */
+
+/* Clock interrupt register */
+
+#define RCC_CIR_LSIRDYF (1 << 0) /* Bit 0: LSI Ready Interrupt flag */
+#define RCC_CIR_LSERDYF (1 << 1) /* Bit 1: LSE Ready Interrupt flag */
+#define RCC_CIR_HSIRDYF (1 << 2) /* Bit 2: HSI Ready Interrupt flag */
+#define RCC_CIR_HSERDYF (1 << 3) /* Bit 3: HSE Ready Interrupt flag */
+#define RCC_CIR_PLLRDYF (1 << 4) /* Bit 4: PLL Ready Interrupt flag */
+#define RCC_CIR_CSSF (1 << 7) /* Bit 7: Clock Security System Interrupt flag */
+#define RCC_CIR_LSIRDYIE (1 << 8) /* Bit 8: LSI Ready Interrupt Enable */
+#define RCC_CIR_LSERDYIE (1 << 9) /* Bit 9: LSE Ready Interrupt Enable */
+#define RCC_CIR_HSIRDYIE (1 << 10) /* Bit 10: HSI Ready Interrupt Enable */
+#define RCC_CIR_HSERDYIE (1 << 11) /* Bit 11: HSE Ready Interrupt Enable */
+#define RCC_CIR_PLLRDYIE (1 << 12) /* Bit 12: PLL Ready Interrupt Enable */
+#define RCC_CIR_LSIRDYC (1 << 16) /* Bit 16: LSI Ready Interrupt Clear */
+#define RCC_CIR_LSERDYC (1 << 17) /* Bit 17: LSE Ready Interrupt Clear */
+#define RCC_CIR_HSIRDYC (1 << 18) /* Bit 18: HSI Ready Interrupt Clear */
+#define RCC_CIR_HSERDYC (1 << 19) /* Bit 19: HSE Ready Interrupt Clear */
+#define RCC_CIR_PLLRDYC (1 << 20) /* Bit 20: PLL Ready Interrupt Clear */
+#define RCC_CIR_CSSC (1 << 23) /* Bit 23: Clock Security System Interrupt Clear */
+
+/* APB2 Peripheral reset register */
+
+#define RCC_APB2RSTR_AFIORST (1 << 0) /* Bit 0: Alternate Function I/O reset */
+#define RCC_APB2RSTR_IOPARST (1 << 2) /* Bit 2: I/O port A reset */
+#define RCC_APB2RSTR_IOPBRST (1 << 3) /* Bit 3: IO port B reset */
+#define RCC_APB2RSTR_IOPCRST (1 << 4) /* Bit 4: IO port C reset */
+#define RCC_APB2RSTR_IOPDRST (1 << 5) /* Bit 5: IO port D reset */
+#define RCC_APB2RSTR_IOPERST (1 << 6) /* Bit 6: IO port E reset */
+#define TCC_APB2RSTR_IOPFRST (1 << 7) /* Bit 7: IO port F reset */
+#define TCC_APB2RSTR_IOPGRST (1 << 8) /* Bit 8: IO port G reset */
+#define RCC_APB2RSTR_ADC1RST (1 << 9) /* Bit 9: ADC 1 interface reset */
+#define RCC_APB2RSTR_ADC2RST (1 << 10) /* Bit 10: ADC 2 interface reset */
+#define RCC_APB2RSTR_TIM1RST (1 << 11) /* Bit 11: TIM1 Timer reset */
+#define RCC_APB2RSTR_SPI1RST (1 << 12) /* Bit 12: SPI 1 reset */
+#define RCC_APB2RSTR_TIM8RST (1 << 13) /* Bit 13: TIM8 Timer reset */
+#define RCC_APB2RSTR_USART1RST (1 << 14) /* Bit 14: USART1 reset */
+#define RCC_APB2RSTR_ADC3RST (1 << 15) /* Bit 15: ADC3 interface reset */
+
+/* APB1 Peripheral reset register */
+
+#define RCC_APB1RSTR_TIM2RST (1 << 0) /* Bit 0: Timer 2 reset */
+#define RCC_APB1RSTR_TIM3RST (1 << 1) /* Bit 1: Timer 3 reset */
+#define RCC_APB1RSTR_TIM4RST (1 << 2) /* Bit 2: Timer 4 reset */
+#define RCC_APB1RSTR_TIM5RST (1 << 3) /* Bit 3: Timer 5 reset */
+#define RCC_APB1RSTR_TIM6RST (1 << 4) /* Bit 4: Timer 6 reset */
+#define RCC_APB1RSTR_TIM7RST (1 << 5) /* Bit 5: Timer 7 reset */
+#define RCC_APB1RSTR_WWDGRST (1 << 11) /* Bit 11: Window Watchdog reset */
+#define RCC_APB1RSTR_SPI2RST (1 << 14) /* Bit 14: SPI 2 reset */
+#define RCC_APB1RSTR_SPI3RST (1 << 15) /* Bit 15: SPI 3 reset */
+#define RCC_APB1RSTR_USART2RST (1 << 17) /* Bit 17: USART 2 reset */
+#define RCC_APB1RSTR_USART3RST (1 << 18) /* Bit 18: USART 3 reset */
+#define RCC_APB1RSTR_UART4RST (1 << 19) /* Bit 19: UART 4 reset */
+#define RCC_APB1RSTR_UART5RST (1 << 20) /* Bit 18: UART 5 reset */
+#define RCC_APB1RSTR_I2C1RST (1 << 21) /* Bit 21: I2C 1 reset */
+#define RCC_APB1RSTR_I2C2RST (1 << 22) /* Bit 22: I2C 2 reset */
+#define RCC_APB1RSTR_USBRST (1 << 23) /* Bit 23: USB reset */
+#define RCC_APB1RSTR_CAN1RST (1 << 25) /* Bit 25: CAN1 reset */
+#define RCC_APB1RSTR_CAN2RST (1 << 26) /* Bit 26: CAN2 reset */
+#define RCC_APB1RSTR_BKPRST (1 << 27) /* Bit 27: Backup interface reset */
+#define RCC_APB1RSTR_PWRRST (1 << 28) /* Bit 28: Power interface reset */
+#define RCC_APB1RSTR_DACRST (1 << 29) /* Bit 29: DAC interface reset */
+
+/* AHB Peripheral Clock enable register */
+
+#define RCC_AHBENR_DMA1EN (1 << 0) /* Bit 0: DMA1 clock enable */
+#define RCC_AHBENR_DMA2EN (1 << 1) /* Bit 1: DMA2 clock enable */
+#define RCC_AHBENR_SRAMEN (1 << 2) /* Bit 2: SRAM interface clock enable */
+#define RCC_AHBENR_FLITFEN (1 << 4) /* Bit 4: FLITF clock enable */
+#define RCC_AHBENR_CRCEN (1 << 6) /* Bit 6: CRC clock enable */
+#define RCC_AHBENR_FSMCEN (1 << 8) /* Bit 8: FSMC clock enable */
+#define RCC_AHBENR_SDIOEN (1 << 10) /* Bit 10: SDIO clock enable */
+
+/* APB2 Peripheral Clock enable register */
+
+#define RCC_APB2ENR_AFIOEN (1 << 0) /* Bit 0: Alternate Function I/O clock enable */
+#define RCC_APB2ENR_IOPEN(n) (1 << ((n)+2))
+#define RCC_APB2ENR_IOPAEN (1 << 2) /* Bit 2: I/O port A clock enable */
+#define RCC_APB2ENR_IOPBEN (1 << 3) /* Bit 3: I/O port B clock enable */
+#define RCC_APB2ENR_IOPCEN (1 << 4) /* Bit 4: I/O port C clock enable */
+#define RCC_APB2ENR_IOPDEN (1 << 5) /* Bit 5: I/O port D clock enable */
+#define RCC_APB2ENR_IOPEEN (1 << 6) /* Bit 6: I/O port E clock enable */
+#define RCC_APB2ENR_IOPFEN (1 << 7) /* Bit 7: I/O port F clock enable */
+#define RCC_APB2ENR_IOPGEN (1 << 8) /* Bit 8: I/O port G clock enable */
+#define RCC_APB2ENR_ADC1EN (1 << 9) /* Bit 9: ADC 1 interface clock enable */
+#define RCC_APB2ENR_ADC2EN (1 << 10) /* Bit 10: ADC 2 interface clock enable */
+#define RCC_APB2ENR_TIM1EN (1 << 11) /* Bit 11: TIM1 Timer clock enable */
+#define RCC_APB2ENR_SPI1EN (1 << 12) /* Bit 12: SPI 1 clock enable */
+#define RCC_APB2ENR_TIM8EN (1 << 13) /* Bit 13: TIM8 Timer clock enable */
+#define RCC_APB2ENR_USART1EN (1 << 14) /* Bit 14: USART1 clock enable */
+#define RCC_APB2ENR_ADC3EN (1 << 15) /* Bit 14: ADC3 interface clock enable */
+
+/* APB1 Peripheral Clock enable register */
+
+#define RCC_APB1ENR_TIM2EN (1 << 0) /* Bit 0: Timer 2 clock enable */
+#define RCC_APB1ENR_TIM3EN (1 << 1) /* Bit 1: Timer 3 clock enable */
+#define RCC_APB1ENR_TIM4EN (1 << 2) /* Bit 2: Timer 4 clock enable */
+#define RCC_APB1ENR_TIM5EN (1 << 3) /* Bit 3: Timer 5 clock enable */
+#define RCC_APB1ENR_TIM6EN (1 << 4) /* Bit 4: Timer 6 clock enable */
+#define RCC_APB1ENR_TIM7EN (1 << 5) /* Bit 5: Timer 7 clock enable */
+#define RCC_APB1ENR_WWDGEN (1 << 11) /* Bit 11: Window Watchdog clock enable */
+#define RCC_APB1ENR_SPI2EN (1 << 14) /* Bit 14: SPI 2 clock enable */
+#define RCC_APB1ENR_SPI3EN (1 << 15) /* Bit 15: SPI 3 clock enable */
+#define RCC_APB1ENR_USART2EN (1 << 17) /* Bit 17: USART 2 clock enable */
+#define RCC_APB1ENR_USART3EN (1 << 18) /* Bit 18: USART 3 clock enable */
+#define RCC_APB1ENR_UART4EN (1 << 19) /* Bit 19: UART 4 clock enable */
+#define RCC_APB1ENR_UART5EN (1 << 20) /* Bit 20: UART 5 clock enable */
+#define RCC_APB1ENR_I2C1EN (1 << 21) /* Bit 21: I2C 1 clock enable */
+#define RCC_APB1ENR_I2C2EN (1 << 22) /* Bit 22: I2C 2 clock enable */
+#define RCC_APB1ENR_USBEN (1 << 23) /* Bit 23: USB clock enable */
+#define RCC_APB1ENR_CAN1EN (1 << 25) /* Bit 25: CAN1 clock enable */
+#define RCC_APB1ENR_CAN2EN (1 << 26) /* Bit 25: CAN2 clock enable */
+#define RCC_APB1ENR_BKPEN (1 << 27) /* Bit 27: Backup interface clock enable */
+#define RCC_APB1ENR_PWREN (1 << 28) /* Bit 28: Power interface clock enable */
+#define RCC_APB1ENR_DACEN (1 << 29) /* Bit 29: DAC interface clock enable */
+
+/* Backup domain control register */
+
+#define RCC_BDCR_BDRST (1 << 16) /* Bit 16: Backup domain software reset */
+#define RCC_BDCR_RTCEN (1 << 15) /* Bit 15: RTC clock enable */
+#define RCC_BDCR_RTCSEL_SHIFT (8) /* Bits 9:8: RTC clock source selection */
+#define RCC_BDCR_RTCSEL_MASK (3 << RCC_BDCR_RTCSEL_SHIFT)
+# define RCC_BDCR_RTCSEL_NOCLK (0 << RCC_BDCR_RTCSEL_SHIFT) /* 00: No clock */
+# define RCC_BDCR_RTCSEL_LSE (1 << RCC_BDCR_RTCSEL_SHIFT) /* 01: LSE oscillator clock used as RTC clock */
+# define RCC_BDCR_RTCSEL_LSI (2 << RCC_BDCR_RTCSEL_SHIFT) /* 10: LSI oscillator clock used as RTC clock */
+# define RCC_BDCR_RTCSEL_HSE (3 << RCC_BDCR_RTCSEL_SHIFT) /* 11: HSE oscillator clock divided by 128 used as RTC clock */
+#define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */
+#define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */
+#define RCC_BDCR_LSEON (1 << 0) /* Bit 0: External Low Speed oscillator enable */
+
+/* Control/status register */
+
+#define RCC_CSR_LSION (1 << 0) /* Bit 0: Internal Low Speed oscillator enable */
+#define RCC_CSR_LSIRDY (1 << 1) /* Bit 1: Internal Low Speed oscillator Ready */
+#define RCC_CSR_RMVF (1 << 24) /* Bit 24: Remove reset flag */
+#define RCC_CSR_PINRSTF (1 << 26) /* Bit 26: PIN reset flag */
+#define RCC_CSR_PORRSTF (1 << 27) /* Bit 27: POR/PDR reset flag */
+#define RCC_CSR_SFTRSTF (1 << 28) /* Bit 28: Software Reset flag */
+#define RCC_CSR_IWDGRSTF (1 << 29) /* Bit 29: Independent Watchdog reset flag */
+#define RCC_CSR_WWDGRSTF (1 << 30) /* Bit 30: Window watchdog reset flag */
+#define RCC_CSR_LPWRRSTF (1 << 31) /* Bit 31: Low-Power reset flag */
+
+#ifdef CONFIG_STM32_VALUELINE
+
+/* Clock configuration register 2 */
+
+# define RCC_CFGR2_PREDIV1d1 0 /* HSE input not divided */
+# define RCC_CFGR2_PREDIV1d2 1 /* HSE input divided by 2 */
+# define RCC_CFGR2_PREDIV1d3 2 /* HSE input divided by 3 */
+# define RCC_CFGR2_PREDIV1d4 3 /* HSE input divided by 4 */
+# define RCC_CFGR2_PREDIV1d5 4 /* HSE input divided by 5 */
+# define RCC_CFGR2_PREDIV1d6 5 /* HSE input divided by 6 */
+# define RCC_CFGR2_PREDIV1d7 6 /* HSE input divided by 7 */
+# define RCC_CFGR2_PREDIV1d8 7 /* HSE input divided by 8 */
+# define RCC_CFGR2_PREDIV1d9 8 /* HSE input divided by 9 */
+# define RCC_CFGR2_PREDIV1d10 9 /* HSE input divided by 10 */
+# define RCC_CFGR2_PREDIV1d11 10 /* HSE input divided by 11 */
+# define RCC_CFGR2_PREDIV1d12 11 /* HSE input divided by 12 */
+# define RCC_CFGR2_PREDIV1d13 12 /* HSE input divided by 13 */
+# define RCC_CFGR2_PREDIV1d14 13 /* HSE input divided by 14 */
+# define RCC_CFGR2_PREDIV1d15 14 /* HSE input divided by 15 */
+# define RCC_CFGR2_PREDIV1d16 15 /* HSE input divided by 16 */
+
+#endif
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RCC_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rtc.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rtc.h
new file mode 100644
index 000000000..a0778f4e6
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_rtc.h
@@ -0,0 +1,96 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f10xxx_rtc.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_CHIP_STM32F10XXX_RTC_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RTC_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_RTC_CRH_OFFSET 0x0000 /* RTC control register High (16-bit) */
+#define STM32_RTC_CRL_OFFSET 0x0004 /* RTC control register low (16-bit) */
+#define STM32_RTC_PRLH_OFFSET 0x0008 /* RTC prescaler load register high (16-bit) */
+#define STM32_RTC_PRLL_OFFSET 0x000c /* RTC prescaler load register low (16-bit) */
+#define STM32_RTC_DIVH_OFFSET 0x0010 /* RTC prescaler divider register high (16-bit) */
+#define STM32_RTC_DIVL_OFFSET 0x0014 /* RTC prescaler divider register low (16-bit) */
+#define STM32_RTC_CNTH_OFFSET 0x0018 /* RTC counter register high (16-bit) */
+#define STM32_RTC_CNTL_OFFSET 0x001c /* RTC counter register low (16-bit) */
+#define STM32_RTC_ALRH_OFFSET 0x0020 /* RTC alarm register high (16-bit) */
+#define STM32_RTC_ALRL_OFFSET 0x0024 /* RTC alarm register low (16-bit) */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_RTC_CRH (STM32_RTC_BASE+STM32_RTC_CRH_OFFSET)
+#define STM32_RTC_CRL (STM32_RTC_BASE+STM32_RTC_CRL_OFFSET)
+#define STM32_RTC_PRLH (STM32_RTC_BASE+STM32_RTC_PRLH_OFFSET)
+#define STM32_RTC_PRLL (STM32_RTC_BASE+STM32_RTC_PRLL_OFFSET)
+#define STM32_RTC_DIVH (STM32_RTC_BASE+STM32_RTC_DIVH_OFFSET)
+#define STM32_RTC_DIVL (STM32_RTC_BASE+STM32_RTC_DIVL_OFFSET)
+#define STM32_RTC_CNTH (STM32_RTC_BASE+STM32_RTC_CNTH_OFFSET)
+#define STM32_RTC_CNTL (STM32_RTC_BASE+STM32_RTC_CNTL_OFFSET)
+#define STM32_RTC_ALRH (STM32_RTC_BASE+STM32_RTC_ALRH_OFFSET)
+#define STM32_RTC_ALRL (STM32_RTC_BASE+STM32_RTC_ALRL_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* RTC control register High (16-bit) */
+
+#define RTC_CRH_SECIE (1 << 0) /* Bit 0 : Second Interrupt Enable */
+#define RTC_CRH_ALRIE (1 << 1) /* Bit 1: Alarm Interrupt Enable */
+#define RTC_CRH_OWIE (1 << 2) /* Bit 2: OverfloW Interrupt Enable */
+
+/* RTC control register low (16-bit) */
+
+#define RTC_CRL_SECF (1 << 0) /* Bit 0: Second Flag */
+#define RTC_CRL_ALRF (1 << 1) /* Bit 1: Alarm Flag */
+#define RTC_CRL_OWF (1 << 2) /* Bit 2: Overflow Flag */
+#define RTC_CRL_RSF (1 << 3) /* Bit 3: Registers Synchronized Flag */
+#define RTC_CRL_CNF (1 << 4) /* Bit 4: Configuration Flag */
+#define RTC_CRL_RTOFF (1 << 5) /* Bit 5: RTC operation OFF */
+
+/* RTC prescaler load register high (16-bit) */
+
+#define RTC_PRLH_PRL_SHIFT (0) /* Bits 3-0: RTC Prescaler Reload Value High */
+#define RTC_PRLH_PRL_MASK (0x0f << RTC_PRLH_PRL_SHIFT)
+
+/* RTC prescaler divider register high (16-bit) */
+
+#define RTC_DIVH_RTC_DIV_SHIFT (0) /* Bits 3-0: RTC Clock Divider High */
+#define RTC_DIVH_RTC_DIV_MASK (0x0f << RTC_DIVH_RTC_DIV_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F10XXX_RTC_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_vectors.h b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_vectors.h
new file mode 100644
index 000000000..d18c7e789
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f10xxx_vectors.h
@@ -0,0 +1,214 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f10xxx_vectors.h
+ *
+ * Copyright (C) 2011 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.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ * Pre-processor definitions
+ ************************************************************************************/
+/* This file is included by stm32_vectors.S. It provides the macro VECTOR that
+ * supplies ach STM32F10xxx vector in terms of a (lower-case) ISR label and an
+ * (upper-case) IRQ number as defined in arch/arm/include/stm32/stm32f10xxx_irq.h.
+ * stm32_vectors.S will defined the VECTOR in different ways in order to generate
+ * the interrupt vectors and handlers in their final form.
+ */
+
+#if defined(CONFIG_STM32_VALUELINE)
+
+/* If the common ARMv7-M vector handling is used, then all it needs is the following
+ * definition that provides the number of supported vectors.
+ */
+
+#ifdef CONFIG_ARMV7M_CMNVECTOR
+
+/* Reserve 60 interrupt table entries for I/O interrupts. */
+
+# define ARMV7M_PERIPHERAL_INTERRUPTS 60
+
+#else
+# error This target requires CONFIG_ARMV7M_CMNVECTOR
+#endif /* CONFIG_ARMV7M_CMNVECTOR */
+
+#elif defined(CONFIG_STM32_CONNECTIVITYLINE)
+
+/* If the common ARMv7-M vector handling is used, then all it needs is the following
+ * definition that provides the number of supported vectors.
+ */
+
+#ifdef CONFIG_ARMV7M_CMNVECTOR
+
+/* Reserve 68 interrupt table entries for I/O interrupts. */
+
+# define ARMV7M_PERIPHERAL_INTERRUPTS 68
+
+#else
+
+VECTOR(stm32_wwdg, STM32_IRQ_WWDG) /* Vector 16+0: Window Watchdog interrupt */
+VECTOR(stm32_pvd, STM32_IRQ_PVD) /* Vector 16+1: PVD through EXTI Line detection interrupt */
+VECTOR(stm32_tamper, STM32_IRQ_TAMPER) /* Vector 16+2: Tamper interrupt */
+VECTOR(stm32_rtc, STM32_IRQ_RTC) /* Vector 16+3: RTC global interrupt */
+VECTOR(stm32_flash, STM32_IRQ_FLASH) /* Vector 16+4: Flash global interrupt */
+VECTOR(stm32_rcc, STM32_IRQ_RCC) /* Vector 16+5: RCC global interrupt */
+VECTOR(stm32_exti0, STM32_IRQ_EXTI0) /* Vector 16+6: EXTI Line 0 interrupt */
+VECTOR(stm32_exti1, STM32_IRQ_EXTI1) /* Vector 16+7: EXTI Line 1 interrupt */
+VECTOR(stm32_exti2, STM32_IRQ_EXTI2) /* Vector 16+8: EXTI Line 2 interrupt */
+VECTOR(stm32_exti3, STM32_IRQ_EXTI3) /* Vector 16+9: EXTI Line 3 interrupt */
+VECTOR(stm32_exti4, STM32_IRQ_EXTI4) /* Vector 16+10: EXTI Line 4 interrupt */
+VECTOR(stm32_dma1ch1, STM32_IRQ_DMA1CH1) /* Vector 16+11: DMA1 Channel 1 global interrupt */
+VECTOR(stm32_dma1ch2, STM32_IRQ_DMA1CH2) /* Vector 16+12: DMA1 Channel 2 global interrupt */
+VECTOR(stm32_dma1ch3, STM32_IRQ_DMA1CH3) /* Vector 16+13: DMA1 Channel 3 global interrupt */
+VECTOR(stm32_dma1ch4, STM32_IRQ_DMA1CH4) /* Vector 16+14: DMA1 Channel 4 global interrupt */
+VECTOR(stm32_dma1ch5, STM32_IRQ_DMA1CH5) /* Vector 16+15: DMA1 Channel 5 global interrupt */
+VECTOR(stm32_dma1ch6, STM32_IRQ_DMA1CH6) /* Vector 16+16: DMA1 Channel 7 global interrupt */
+VECTOR(stm32_adc12, STM32_IRQ_ADC12) /* Vector 16+18: ADC1 and ADC2 global interrupt */
+VECTOR(stm32_can1tx, STM32_IRQ_CAN1TX) /* Vector 16+19: CAN1 TX interrupts */
+VECTOR(stm32_can1rx0, STM32_IRQ_CAN1RX0) /* Vector 16+20: CAN1 RX0 interrupts */
+VECTOR(stm32_can1rx, STM32_IRQ_CAN1RX1) /* Vector 16+21: CAN1 RX1 interrupt */
+VECTOR(stm32_can1sce, STM32_IRQ_CAN1SCE) /* Vector 16+22: CAN1 SCE interrupt */
+VECTOR(stm32_exti95, STM32_IRQ_EXTI95) /* Vector 16+23: EXTI Line[9:5] interrupts */
+VECTOR(stm32_tim1brk, STM32_IRQ_TIM1BRK) /* Vector 16+24: TIM1 Break interrupt */
+VECTOR(stm32_tim1up, STM32_IRQ_TIM1UP) /* Vector 16+25: TIM1 Update interrupt */
+VECTOR(stm32_tim1trgcom, STM32_IRQ_TIM1TRGCOM) /* Vector 16+26: TIM1 Trigger and Commutation interrupts */
+VECTOR(stm32_tim1cc, STM32_IRQ_TIM1CC) /* Vector 16+27: TIM1 Capture Compare interrupt */
+VECTOR(stm32_tim2, STM32_IRQ_TIM2) /* Vector 16+28: TIM2 global interrupt */
+VECTOR(stm32_tim3, STM32_IRQ_TIM3) /* Vector 16+29: TIM3 global interrupt */
+VECTOR(stm32_tim4, STM32_IRQ_TIM4) /* Vector 16+30: TIM4 global interrupt */
+VECTOR(stm32_i2c1ev, STM32_IRQ_I2C1EV) /* Vector 16+31: I2C1 event interrupt */
+VECTOR(stm32_i2c1er, STM32_IRQ_I2C1ER) /* Vector 16+32: I2C1 error interrupt */
+VECTOR(stm32_i2c2ev, STM32_IRQ_I2C2EV) /* Vector 16+33: I2C2 event interrupt */
+VECTOR(stm32_i2c2er, STM32_IRQ_I2C2ER) /* Vector 16+34: I2C2 error interrupt */
+VECTOR(stm32_spi1, STM32_IRQ_SPI1) /* Vector 16+35: SPI1 global interrupt */
+VECTOR(stm32_spi2, STM32_IRQ_SPI2) /* Vector 16+36: SPI2 global interrupt */
+VECTOR(stm32_usart1, STM32_IRQ_USART1) /* Vector 16+37: USART1 global interrupt */
+VECTOR(stm32_usart2, STM32_IRQ_USART2) /* Vector 16+38: USART2 global interrupt */
+VECTOR(stm32_usart3, STM32_IRQ_USART3) /* Vector 16+39: USART3 global interrupt */
+VECTOR(stm32_exti1510, STM32_IRQ_EXTI1510) /* Vector 16+40: EXTI Line[15:10] interrupts */
+VECTOR(stm32_rtcalr, STM32_IRQ_RTCALRM) /* Vector 16+41: RTC alarm through EXTI line interrupt */
+VECTOR(stm32_otgfswkup, STM32_IRQ_OTGFSWKUP) /* Vector 16+42: USB On-The-Go FS Wakeup through EXTI line interrupt */
+VECTOR(stm32_tim5, STM32_IRQ_TIM5) /* Vector 16+50: TIM5 global interrupt */
+VECTOR(stm32_spi3, STM32_IRQ_SPI3 ) /* Vector 16+51: SPI3 global interrupt */
+VECTOR(stm32_uart4 , STM32_IRQ_UART4) /* Vector 16+52: UART4 global interrupt */
+VECTOR(stm32_uart5, STM32_IRQ_UART5) /* Vector 16+53: UART5 global interrupt */
+VECTOR(stm32_tim6, STM32_IRQ_TIM6) /* Vector 16+54: TIM6 global interrupt */
+VECTOR(stm32_tim7, STM32_IRQ_TIM7) /* Vector 16+55: TIM7 global interrupt */
+VECTOR(stm32_dma2ch1, STM32_IRQ_DMA2CH1) /* Vector 16+56: DMA2 Channel 1 global interrupt */
+VECTOR(stm32_dma2ch2, STM32_IRQ_DMA2CH2) /* Vector 16+57: DMA2 Channel 2 global interrupt */
+VECTOR(stm32_dma2ch3, STM32_IRQ_DMA2CH3) /* Vector 16+58: DMA2 Channel 3 global interrupt */
+VECTOR(stm32_dma2ch4, STM32_IRQ_DMA2CH4) /* Vector 16+59: DMA2 Channel 4 global interrupt */
+VECTOR(stm32_dma2ch5, STM32_IRQ_DMA2CH5) /* Vector 16+60: DMA2 Channel 5 global interrupt */
+VECTOR(stm32_eth, STM32_IRQ_ETH) /* Vector 16+61: Ethernet global interrupt */
+VECTOR(stm32_ethwkup, STM32_IRQ_ETHWKUP) /* Vector 16+62: Ethernet Wakeup through EXTI line interrupt */
+VECTOR(stm32_can2tx, STM32_IRQ_CAN2TX) /* Vector 16+63: CAN2 TX interrupts */
+VECTOR(stm32_can2rx0, STM32_IRQ_CAN2RX0) /* Vector 16+64: CAN2 RX0 interrupts */
+VECTOR(stm32_can2rx1, STM32_IRQ_CAN2RX1) /* Vector 16+65: CAN2 RX1 interrupt */
+VECTOR(stm32_can2sce, STM32_IRQ_CAN2SCE) /* Vector 16+66: CAN2 SCE interrupt */
+VECTOR(stm32_otgfs, STM32_IRQ_OTGFS) /* Vector 16+67: USB On The Go FS global interrupt */
+
+#endif /* CONFIG_ARMV7M_CMNVECTOR */
+#else /* CONFIG_STM32_CONNECTIVITYLINE */
+
+/* If the common ARMv7-M vector handling is used, then all it needs is the following
+ * definition that provides the number of supported vectors.
+ */
+
+#ifdef CONFIG_ARMV7M_CMNVECTOR
+
+/* Reserve 60 interrupt table entries for I/O interrupts. */
+
+# define ARMV7M_PERIPHERAL_INTERRUPTS 60
+
+#else
+
+VECTOR(stm32_wwdg, STM32_IRQ_WWDG) /* Vector 16+0: Window Watchdog interrupt */
+VECTOR(stm32_pvd, STM32_IRQ_PVD) /* Vector 16+1: PVD through EXTI Line detection interrupt */
+VECTOR(stm32_tamper, STM32_IRQ_TAMPER) /* Vector 16+2: Tamper interrupt */
+VECTOR(stm32_rtc, STM32_IRQ_RTC) /* Vector 16+3: RTC global interrupt */
+VECTOR(stm32_flash, STM32_IRQ_FLASH) /* Vector 16+4: Flash global interrupt */
+VECTOR(stm32_rcc, STM32_IRQ_RCC) /* Vector 16+5: RCC global interrupt */
+VECTOR(stm32_exti0, STM32_IRQ_EXTI0) /* Vector 16+6: EXTI Line 0 interrupt */
+VECTOR(stm32_exti1, STM32_IRQ_EXTI1) /* Vector 16+7: EXTI Line 1 interrupt */
+VECTOR(stm32_exti2, STM32_IRQ_EXTI2) /* Vector 16+8: EXTI Line 2 interrupt */
+VECTOR(stm32_exti3, STM32_IRQ_EXTI3) /* Vector 16+9: EXTI Line 3 interrupt */
+VECTOR(stm32_exti4, STM32_IRQ_EXTI4) /* Vector 16+10: EXTI Line 4 interrupt */
+VECTOR(stm32_dma1ch1, STM32_IRQ_DMA1CH1) /* Vector 16+11: DMA1 Channel 1 global interrupt */
+VECTOR(stm32_dma1ch2, STM32_IRQ_DMA1CH2) /* Vector 16+12: DMA1 Channel 2 global interrupt */
+VECTOR(stm32_dma1ch3, STM32_IRQ_DMA1CH3) /* Vector 16+13: DMA1 Channel 3 global interrupt */
+VECTOR(stm32_dma1ch4, STM32_IRQ_DMA1CH4) /* Vector 16+14: DMA1 Channel 4 global interrupt */
+VECTOR(stm32_dma1ch5, STM32_IRQ_DMA1CH5) /* Vector 16+15: DMA1 Channel 5 global interrupt */
+VECTOR(stm32_dma1ch6, STM32_IRQ_DMA1CH6) /* Vector 16+16: DMA1 Channel 6 global interrupt */
+VECTOR(stm32_dma1ch7, STM32_IRQ_DMA1CH7) /* Vector 16+17: DMA1 Channel 7 global interrupt */
+VECTOR(stm32_adc12, STM32_IRQ_ADC12) /* Vector 16+18: ADC1 and ADC2 global interrupt */
+VECTOR(stm32_usbhpcantx, STM32_IRQ_USBHPCANTX) /* Vector 16+19: USB High Priority or CAN TX interrupts*/
+VECTOR(stm32_usblpcanrx0, STM32_IRQ_USBLPCANRX0) /* Vector 16+20: USB Low Priority or CAN RX0 interrupts*/
+VECTOR(stm32_can1rx1, STM32_IRQ_CAN1RX1) /* Vector 16+21: CAN1 RX1 interrupt */
+VECTOR(stm32_can1sce, STM32_IRQ_CAN1SCE) /* Vector 16+22: CAN1 SCE interrupt */
+VECTOR(stm32_exti95, STM32_IRQ_EXTI95) /* Vector 16+23: EXTI Line[9:5] interrupts */
+VECTOR(stm32_tim1brk, STM32_IRQ_TIM1BRK) /* Vector 16+24: TIM1 Break interrupt */
+VECTOR(stm32_tim1up, STM32_IRQ_TIM1UP) /* Vector 16+25: TIM1 Update interrupt */
+VECTOR(stm32_tim1rtgcom, STM32_IRQ_TIM1TRGCOM) /* Vector 16+26: TIM1 Trigger and Commutation interrupts */
+VECTOR(stm32_tim1cc, STM32_IRQ_TIM1CC) /* Vector 16+27: TIM1 Capture Compare interrupt */
+VECTOR(stm32_tim2, STM32_IRQ_TIM2) /* Vector 16+28: TIM2 global interrupt */
+VECTOR(stm32_tim3, STM32_IRQ_TIM3) /* Vector 16+29: TIM3 global interrupt */
+VECTOR(stm32_tim4, STM32_IRQ_TIM4) /* Vector 16+30: TIM4 global interrupt */
+VECTOR(stm32_i2c1ev, STM32_IRQ_I2C1EV) /* Vector 16+31: I2C1 event interrupt */
+VECTOR(stm32_i2c1er, STM32_IRQ_I2C1ER) /* Vector 16+32: I2C1 error interrupt */
+VECTOR(stm32_i2c2ev, STM32_IRQ_I2C2EV) /* Vector 16+33: I2C2 event interrupt */
+VECTOR(stm32_i2c2er, STM32_IRQ_I2C2ER) /* Vector 16+34: I2C2 error interrupt */
+VECTOR(stm32_spi1, STM32_IRQ_SPI1) /* Vector 16+35: SPI1 global interrupt */
+VECTOR(stm32_spi2, STM32_IRQ_SPI2) /* Vector 16+36: SPI2 global interrupt */
+VECTOR(stm32_usart1, STM32_IRQ_USART1) /* Vector 16+37: USART1 global interrupt */
+VECTOR(stm32_usart2, STM32_IRQ_USART2) /* Vector 16+38: USART2 global interrupt */
+VECTOR(stm32_usart3, STM32_IRQ_USART3) /* Vector 16+39: USART3 global interrupt */
+VECTOR(stm32_exti1510, STM32_IRQ_EXTI1510) /* Vector 16+40: EXTI Line[15:10] interrupts */
+VECTOR(stm32_rtcalr, STM32_IRQ_RTCALRM) /* Vector 16+41: RTC alarm through EXTI line interrupt */
+VECTOR(stm32_usbwkup, STM32_IRQ_USBWKUP) /* Vector 16+42: USB wakeup from suspend through EXTI line interrupt*/
+VECTOR(stm32_tim8brk, STM32_IRQ_TIM8BRK) /* Vector 16+43: TIM8 Break interrupt */
+VECTOR(stm32_tim8up, STM32_IRQ_TIM8UP) /* Vector 16+44: TIM8 Update interrupt */
+VECTOR(stm32_tim8trgcom, STM32_IRQ_TIM8TRGCOM) /* Vector 16+45: TIM8 Trigger and Commutation interrupts */
+VECTOR(stm32_tim8cc, STM32_IRQ_TIM8CC) /* Vector 16+46: TIM8 Capture Compare interrupt */
+VECTOR(stm32_adc3, STM32_IRQ_ADC3) /* Vector 16+47: ADC3 global interrupt */
+VECTOR(stm32_fsmc, STM32_IRQ_FSMC) /* Vector 16+48: FSMC global interrupt */
+VECTOR(stm32_sdio, STM32_IRQ_SDIO) /* Vector 16+49: SDIO global interrupt */
+VECTOR(stm32_tim5, STM32_IRQ_TIM5) /* Vector 16+50: TIM5 global interrupt */
+VECTOR(stm32_spi3, STM32_IRQ_SPI3) /* Vector 16+51: SPI3 global interrupt */
+VECTOR(stm32_uart4, STM32_IRQ_UART4) /* Vector 16+52: UART4 global interrupt */
+VECTOR(stm32_uart5, STM32_IRQ_UART5) /* Vector 16+53: UART5 global interrupt */
+VECTOR(stm32_tim6, STM32_IRQ_TIM6) /* Vector 16+54: TIM6 global interrupt */
+VECTOR(stm32_tim7, STM32_IRQ_TIM7) /* Vector 16+55: TIM7 global interrupt */
+VECTOR(stm32_dma2ch1, STM32_IRQ_DMA2CH1) /* Vector 16+56: DMA2 Channel 1 global interrupt */
+VECTOR(stm32_dma2ch2, STM32_IRQ_DMA2CH2) /* Vector 16+57: DMA2 Channel 2 global interrupt */
+VECTOR(stm32_dma2ch3, STM32_IRQ_DMA2CH3) /* Vector 16+58: DMA2 Channel 3 global interrupt */
+VECTOR(stm32_dma2ch45, STM32_IRQ_DMA2CH45) /* Vector 16+59: DMA2 Channel 4&5 global interrupt */
+
+#endif /* CONFIG_ARMV7M_CMNVECTOR */
+#endif /* CONFIG_STM32_CONNECTIVITYLINE */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_dma.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_dma.h
new file mode 100644
index 000000000..af4b361c2
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_dma.h
@@ -0,0 +1,520 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f20xxx_dma.h
+ *
+ * Copyright (C) 2012 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_STM32_CHIP_STM32F20XXX_DMA_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_DMA_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* 2 DMA controllers */
+
+#define DMA1 (0)
+#define DMA2 (1)
+
+/* 8 DMA streams */
+
+#define DMA_STREAM0 (0)
+#define DMA_STREAM1 (1)
+#define DMA_STREAM2 (2)
+#define DMA_STREAM3 (3)
+#define DMA_STREAM4 (4)
+#define DMA_STREAM5 (5)
+#define DMA_STREAM6 (6)
+#define DMA_STREAM7 (7)
+
+/* 8 DMA channels */
+
+#define DMA_CHAN0 (0)
+#define DMA_CHAN1 (1)
+#define DMA_CHAN2 (2)
+#define DMA_CHAN3 (3)
+#define DMA_CHAN4 (4)
+#define DMA_CHAN5 (5)
+#define DMA_CHAN6 (6)
+#define DMA_CHAN7 (7)
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_DMA_LISR_OFFSET 0x0000 /* DMA low interrupt status register */
+#define STM32_DMA_HISR_OFFSET 0x0004 /* DMA high interrupt status register */
+#define STM32_DMA_LIFCR_OFFSET 0x0008 /* DMA low interrupt flag clear register */
+#define STM32_DMA_HIFCR_OFFSET 0x000c /* DMA high interrupt flag clear register */
+
+#define STM32_DMA_OFFSET(n) (0x0010+0x0018*(n))
+#define STM32_DMA_SCR_OFFSET 0x0000 /* DMA stream n configuration register */
+#define STM32_DMA_SNDTR_OFFSET 0x0004 /* DMA stream n number of data register */
+#define STM32_DMA_SPAR_OFFSET 0x0008 /* DMA stream n peripheral address register */
+#define STM32_DMA_SM0AR_OFFSET 0x000c /* DMA stream n memory 0 address register */
+#define STM32_DMA_SM1AR_OFFSET 0x0010 /* DMA stream n memory 1 address register */
+#define STM32_DMA_SFCR_OFFSET 0x0014 /* DMA stream n FIFO control register */
+
+#define STM32_DMA_S0CR_OFFSET 0x0010 /* DMA stream 0 configuration register */
+#define STM32_DMA_S1CR_OFFSET 0x0028 /* DMA stream 1 configuration register */
+#define STM32_DMA_S2CR_OFFSET 0x0040 /* DMA stream 2 configuration register */
+#define STM32_DMA_S3CR_OFFSET 0x0058 /* DMA stream 3 configuration register */
+#define STM32_DMA_S4CR_OFFSET 0x0070 /* DMA stream 4 configuration register */
+#define STM32_DMA_S5CR_OFFSET 0x0088 /* DMA stream 5 configuration register */
+#define STM32_DMA_S6CR_OFFSET 0x00a0 /* DMA stream 6 configuration register */
+#define STM32_DMA_S7CR_OFFSET 0x00b8 /* DMA stream 7 configuration register */
+
+#define STM32_DMA_S0NDTR_OFFSET 0x0014 /* DMA stream 0 number of data register */
+#define STM32_DMA_S1NDTR_OFFSET 0x002c /* DMA stream 1 number of data register */
+#define STM32_DMA_S2NDTR_OFFSET 0x0044 /* DMA stream 2 number of data register */
+#define STM32_DMA_S3NDTR_OFFSET 0x005c /* DMA stream 3 number of data register */
+#define STM32_DMA_S4NDTR_OFFSET 0x0074 /* DMA stream 4 number of data register */
+#define STM32_DMA_S5NDTR_OFFSET 0x008c /* DMA stream 5 number of data register */
+#define STM32_DMA_S6NDTR_OFFSET 0x00a4 /* DMA stream 6 number of data register */
+#define STM32_DMA_S7NDTR_OFFSET 0x00bc /* DMA stream 7 number of data register */
+
+#define STM32_DMA_S0PAR_OFFSET 0x0018 /* DMA stream 0 peripheral address register */
+#define STM32_DMA_S1PAR_OFFSET 0x0030 /* DMA stream 1 peripheral address register */
+#define STM32_DMA_S2PAR_OFFSET 0x0048 /* DMA stream 2 peripheral address register */
+#define STM32_DMA_S3PAR_OFFSET 0x0060 /* DMA stream 3 peripheral address register */
+#define STM32_DMA_S4PAR_OFFSET 0x0078 /* DMA stream 4 peripheral address register */
+#define STM32_DMA_S5PAR_OFFSET 0x0090 /* DMA stream 5 peripheral address register */
+#define STM32_DMA_S6PAR_OFFSET 0x00a8 /* DMA stream 6 peripheral address register */
+#define STM32_DMA_S7PAR_OFFSET 0x00c0 /* DMA stream 7 peripheral address register */
+
+#define STM32_DMA_S0M0AR_OFFSET 0x001c /* DMA stream 0 memory 0 address register */
+#define STM32_DMA_S1M0AR_OFFSET 0x0034 /* DMA stream 1 memory 0 address register */
+#define STM32_DMA_S2M0AR_OFFSET 0x004c /* DMA stream 2 memory 0 address register */
+#define STM32_DMA_S3M0AR_OFFSET 0x0064 /* DMA stream 3 memory 0 address register */
+#define STM32_DMA_S4M0AR_OFFSET 0x007c /* DMA stream 4 memory 0 address register */
+#define STM32_DMA_S5M0AR_OFFSET 0x0094 /* DMA stream 5 memory 0 address register */
+#define STM32_DMA_S6M0AR_OFFSET 0x00ac /* DMA stream 6 memory 0 address register */
+#define STM32_DMA_S7M0AR_OFFSET 0x00c4 /* DMA stream 7 memory 0 address register */
+
+#define STM32_DMA_S0M1AR_OFFSET 0x0020 /* DMA stream 0 memory 1 address register */
+#define STM32_DMA_S1M1AR_OFFSET 0x0038 /* DMA stream 1 memory 1 address register */
+#define STM32_DMA_S2M1AR_OFFSET 0x0050 /* DMA stream 2 memory 1 address register */
+#define STM32_DMA_S3M1AR_OFFSET 0x0068 /* DMA stream 3 memory 1 address register */
+#define STM32_DMA_S4M1AR_OFFSET 0x0080 /* DMA stream 4 memory 1 address register */
+#define STM32_DMA_S5M1AR_OFFSET 0x0098 /* DMA stream 5 memory 1 address register */
+#define STM32_DMA_S6M1AR_OFFSET 0x00b0 /* DMA stream 6 memory 1 address register */
+#define STM32_DMA_S7M1AR_OFFSET 0x00c8 /* DMA stream 7 memory 1 address register */
+
+#define STM32_DMA_S0FCR_OFFSET 0x0024 /* DMA stream 0 FIFO control register */
+#define STM32_DMA_S1FCR_OFFSET 0x003c /* DMA stream 1 FIFO control register */
+#define STM32_DMA_S2FCR_OFFSET 0x0054 /* DMA stream 2 FIFO control register */
+#define STM32_DMA_S3FCR_OFFSET 0x006c /* DMA stream 3 FIFO control register */
+#define STM32_DMA_S4FCR_OFFSET 0x0084 /* DMA stream 4 FIFO control register */
+#define STM32_DMA_S5FCR_OFFSET 0x009c /* DMA stream 5 FIFO control register */
+#define STM32_DMA_S6FCR_OFFSET 0x00b4 /* DMA stream 6 FIFO control register */
+#define STM32_DMA_S7FCR_OFFSET 0x00cc /* DMA stream 7 FIFO control register */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_DMA1_LISRC (STM32_DMA1_BASE+STM32_DMA_LISR_OFFSET)
+#define STM32_DMA1_HISRC (STM32_DMA1_BASE+STM32_DMA_HISR_OFFSET)
+#define STM32_DMA1_LIFCR (STM32_DMA1_BASE+STM32_DMA_LIFCR_OFFSET)
+#define STM32_DMA1_HIFCR (STM32_DMA1_BASE+STM32_DMA_HIFCR_OFFSET)
+
+#define STM32_DMA1_SCR(n) (STM32_DMA1_BASE+STM32_DMA_SCR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0CR (STM32_DMA1_BASE+STM32_DMA_S0CR_OFFSET)
+#define STM32_DMA1_S1CR (STM32_DMA1_BASE+STM32_DMA_S1CR_OFFSET)
+#define STM32_DMA1_S2CR (STM32_DMA1_BASE+STM32_DMA_S2CR_OFFSET)
+#define STM32_DMA1_S3CR (STM32_DMA1_BASE+STM32_DMA_S3CR_OFFSET)
+#define STM32_DMA1_S4CR (STM32_DMA1_BASE+STM32_DMA_S4CR_OFFSET)
+#define STM32_DMA1_S5CR (STM32_DMA1_BASE+STM32_DMA_S5CR_OFFSET)
+#define STM32_DMA1_S6CR (STM32_DMA1_BASE+STM32_DMA_S6CR_OFFSET)
+#define STM32_DMA1_S7CR (STM32_DMA1_BASE+STM32_DMA_S7CR_OFFSET)
+
+#define STM32_DMA1_SNDTR(n) (STM32_DMA1_BASE+STM32_DMA_SNDTR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0NDTR (STM32_DMA1_BASE+STM32_DMA_S0NDTR_OFFSET)
+#define STM32_DMA1_S1NDTR (STM32_DMA1_BASE+STM32_DMA_S1NDTR_OFFSET)
+#define STM32_DMA1_S2NDTR (STM32_DMA1_BASE+STM32_DMA_S2NDTR_OFFSET)
+#define STM32_DMA1_S3NDTR (STM32_DMA1_BASE+STM32_DMA_S3NDTR_OFFSET)
+#define STM32_DMA1_S4NDTR (STM32_DMA1_BASE+STM32_DMA_S4NDTR_OFFSET)
+#define STM32_DMA1_S5NDTR (STM32_DMA1_BASE+STM32_DMA_S5NDTR_OFFSET)
+#define STM32_DMA1_S6NDTR (STM32_DMA1_BASE+STM32_DMA_S6NDTR_OFFSET)
+#define STM32_DMA1_S7NDTR (STM32_DMA1_BASE+STM32_DMA_S7NDTR_OFFSET)
+
+#define STM32_DMA1_SPAR(n) (STM32_DMA1_BASE+STM32_DMA_SPAR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0PAR (STM32_DMA1_BASE+STM32_DMA_S0PAR_OFFSET)
+#define STM32_DMA1_S1PAR (STM32_DMA1_BASE+STM32_DMA_S1PAR_OFFSET)
+#define STM32_DMA1_S2PAR (STM32_DMA1_BASE+STM32_DMA_S2PAR_OFFSET)
+#define STM32_DMA1_S3PAR (STM32_DMA1_BASE+STM32_DMA_S3PAR_OFFSET)
+#define STM32_DMA1_S4PAR (STM32_DMA1_BASE+STM32_DMA_S4PAR_OFFSET)
+#define STM32_DMA1_S5PAR (STM32_DMA1_BASE+STM32_DMA_S5PAR_OFFSET)
+#define STM32_DMA1_S6PAR (STM32_DMA1_BASE+STM32_DMA_S6PAR_OFFSET)
+#define STM32_DMA1_S7PAR (STM32_DMA1_BASE+STM32_DMA_S7PAR_OFFSET)
+
+#define STM32_DMA1_SM0AR(n) (STM32_DMA1_BASE+STM32_DMA_SM0AR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0M0AR (STM32_DMA1_BASE+STM32_DMA_S0M0AR_OFFSET)
+#define STM32_DMA1_S1M0AR (STM32_DMA1_BASE+STM32_DMA_S1M0AR_OFFSET)
+#define STM32_DMA1_S2M0AR (STM32_DMA1_BASE+STM32_DMA_S2M0AR_OFFSET)
+#define STM32_DMA1_S3M0AR (STM32_DMA1_BASE+STM32_DMA_S3M0AR_OFFSET)
+#define STM32_DMA1_S4M0AR (STM32_DMA1_BASE+STM32_DMA_S4M0AR_OFFSET)
+#define STM32_DMA1_S5M0AR (STM32_DMA1_BASE+STM32_DMA_S5M0AR_OFFSET)
+#define STM32_DMA1_S6M0AR (STM32_DMA1_BASE+STM32_DMA_S6M0AR_OFFSET)
+#define STM32_DMA1_S7M0AR (STM32_DMA1_BASE+STM32_DMA_S7M0AR_OFFSET)
+
+#define STM32_DMA1_SM1AR(n) (STM32_DMA1_BASE+STM32_DMA_SM1AR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0M1AR (STM32_DMA1_BASE+STM32_DMA_S0M1AR_OFFSET)
+#define STM32_DMA1_S1M1AR (STM32_DMA1_BASE+STM32_DMA_S1M1AR_OFFSET)
+#define STM32_DMA1_S2M1AR (STM32_DMA1_BASE+STM32_DMA_S2M1AR_OFFSET)
+#define STM32_DMA1_S3M1AR (STM32_DMA1_BASE+STM32_DMA_S3M1AR_OFFSET)
+#define STM32_DMA1_S4M1AR (STM32_DMA1_BASE+STM32_DMA_S4M1AR_OFFSET)
+#define STM32_DMA1_S5M1AR (STM32_DMA1_BASE+STM32_DMA_S5M1AR_OFFSET)
+#define STM32_DMA1_S6M1AR (STM32_DMA1_BASE+STM32_DMA_S6M1AR_OFFSET)
+#define STM32_DMA1_S7M1AR (STM32_DMA1_BASE+STM32_DMA_S7M1AR_OFFSET)
+
+#define STM32_DMA1_SFCR(n) (STM32_DMA1_BASE+STM32_DMA_SFCR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0FCR (STM32_DMA1_BASE+STM32_DMA_S0FCR_OFFSET)
+#define STM32_DMA1_S1FCR (STM32_DMA1_BASE+STM32_DMA_S1FCR_OFFSET)
+#define STM32_DMA1_S2FCR (STM32_DMA1_BASE+STM32_DMA_S2FCR_OFFSET)
+#define STM32_DMA1_S3FCR (STM32_DMA1_BASE+STM32_DMA_S3FCR_OFFSET)
+#define STM32_DMA1_S4FCR (STM32_DMA1_BASE+STM32_DMA_S4FCR_OFFSET)
+#define STM32_DMA1_S5FCR (STM32_DMA1_BASE+STM32_DMA_S5FCR_OFFSET)
+#define STM32_DMA1_S6FCR (STM32_DMA1_BASE+STM32_DMA_S6FCR_OFFSET)
+#define STM32_DMA1_S7FCR (STM32_DMA1_BASE+STM32_DMA_S7FCR_OFFSET)
+
+#define STM32_DMA2_LISRC (STM32_DMA2_BASE+STM32_DMA_LISR_OFFSET)
+#define STM32_DMA2_HISRC (STM32_DMA2_BASE+STM32_DMA_HISR_OFFSET)
+#define STM32_DMA2_LIFCR (STM32_DMA2_BASE+STM32_DMA_LIFCR_OFFSET)
+#define STM32_DMA2_HIFCR (STM32_DMA2_BASE+STM32_DMA_HIFCR_OFFSET)
+
+#define STM32_DMA2_SCR(n) (STM32_DMA2_BASE+STM32_DMA_SCR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0CR (STM32_DMA2_BASE+STM32_DMA_S0CR_OFFSET)
+#define STM32_DMA2_S1CR (STM32_DMA2_BASE+STM32_DMA_S1CR_OFFSET)
+#define STM32_DMA2_S2CR (STM32_DMA2_BASE+STM32_DMA_S2CR_OFFSET)
+#define STM32_DMA2_S3CR (STM32_DMA2_BASE+STM32_DMA_S3CR_OFFSET)
+#define STM32_DMA2_S4CR (STM32_DMA2_BASE+STM32_DMA_S4CR_OFFSET)
+#define STM32_DMA2_S5CR (STM32_DMA2_BASE+STM32_DMA_S5CR_OFFSET)
+#define STM32_DMA2_S6CR (STM32_DMA2_BASE+STM32_DMA_S6CR_OFFSET)
+#define STM32_DMA2_S7CR (STM32_DMA2_BASE+STM32_DMA_S7CR_OFFSET)
+
+#define STM32_DMA2_SNDTR(n) (STM32_DMA2_BASE+STM32_DMA_SNDTR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0NDTR (STM32_DMA2_BASE+STM32_DMA_S0NDTR_OFFSET)
+#define STM32_DMA2_S1NDTR (STM32_DMA2_BASE+STM32_DMA_S1NDTR_OFFSET)
+#define STM32_DMA2_S2NDTR (STM32_DMA2_BASE+STM32_DMA_S2NDTR_OFFSET)
+#define STM32_DMA2_S3NDTR (STM32_DMA2_BASE+STM32_DMA_S3NDTR_OFFSET)
+#define STM32_DMA2_S4NDTR (STM32_DMA2_BASE+STM32_DMA_S4NDTR_OFFSET)
+#define STM32_DMA2_S5NDTR (STM32_DMA2_BASE+STM32_DMA_S5NDTR_OFFSET)
+#define STM32_DMA2_S6NDTR (STM32_DMA2_BASE+STM32_DMA_S6NDTR_OFFSET)
+#define STM32_DMA2_S7NDTR (STM32_DMA2_BASE+STM32_DMA_S7NDTR_OFFSET)
+
+#define STM32_DMA2_SPAR(n) (STM32_DMA2_BASE+STM32_DMA_SPAR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0PAR (STM32_DMA2_BASE+STM32_DMA_S0PAR_OFFSET)
+#define STM32_DMA2_S1PAR (STM32_DMA2_BASE+STM32_DMA_S1PAR_OFFSET)
+#define STM32_DMA2_S2PAR (STM32_DMA2_BASE+STM32_DMA_S2PAR_OFFSET)
+#define STM32_DMA2_S3PAR (STM32_DMA2_BASE+STM32_DMA_S3PAR_OFFSET)
+#define STM32_DMA2_S4PAR (STM32_DMA2_BASE+STM32_DMA_S4PAR_OFFSET)
+#define STM32_DMA2_S5PAR (STM32_DMA2_BASE+STM32_DMA_S5PAR_OFFSET)
+#define STM32_DMA2_S6PAR (STM32_DMA2_BASE+STM32_DMA_S6PAR_OFFSET)
+#define STM32_DMA2_S7PAR (STM32_DMA2_BASE+STM32_DMA_S7PAR_OFFSET)
+
+#define STM32_DMA2_SM0AR(n) (STM32_DMA2_BASE+STM32_DMA_SM0AR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0M0AR (STM32_DMA2_BASE+STM32_DMA_S0M0AR_OFFSET)
+#define STM32_DMA2_S1M0AR (STM32_DMA2_BASE+STM32_DMA_S1M0AR_OFFSET)
+#define STM32_DMA2_S2M0AR (STM32_DMA2_BASE+STM32_DMA_S2M0AR_OFFSET)
+#define STM32_DMA2_S3M0AR (STM32_DMA2_BASE+STM32_DMA_S3M0AR_OFFSET)
+#define STM32_DMA2_S4M0AR (STM32_DMA2_BASE+STM32_DMA_S4M0AR_OFFSET)
+#define STM32_DMA2_S5M0AR (STM32_DMA2_BASE+STM32_DMA_S5M0AR_OFFSET)
+#define STM32_DMA2_S6M0AR (STM32_DMA2_BASE+STM32_DMA_S6M0AR_OFFSET)
+#define STM32_DMA2_S7M0AR (STM32_DMA2_BASE+STM32_DMA_S7M0AR_OFFSET)
+
+#define STM32_DMA2_SM1AR(n) (STM32_DMA2_BASE+STM32_DMA_SM1AR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0M1AR (STM32_DMA2_BASE+STM32_DMA_S0M1AR_OFFSET)
+#define STM32_DMA2_S1M1AR (STM32_DMA2_BASE+STM32_DMA_S1M1AR_OFFSET)
+#define STM32_DMA2_S2M1AR (STM32_DMA2_BASE+STM32_DMA_S2M1AR_OFFSET)
+#define STM32_DMA2_S3M1AR (STM32_DMA2_BASE+STM32_DMA_S3M1AR_OFFSET)
+#define STM32_DMA2_S4M1AR (STM32_DMA2_BASE+STM32_DMA_S4M1AR_OFFSET)
+#define STM32_DMA2_S5M1AR (STM32_DMA2_BASE+STM32_DMA_S5M1AR_OFFSET)
+#define STM32_DMA2_S6M1AR (STM32_DMA2_BASE+STM32_DMA_S6M1AR_OFFSET)
+#define STM32_DMA2_S7M1AR (STM32_DMA2_BASE+STM32_DMA_S7M1AR_OFFSET)
+
+#define STM32_DMA2_SFCR(n) (STM32_DMA2_BASE+STM32_DMA_SFCR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0FCR (STM32_DMA2_BASE+STM32_DMA_S0FCR_OFFSET)
+#define STM32_DMA2_S1FCR (STM32_DMA2_BASE+STM32_DMA_S1FCR_OFFSET)
+#define STM32_DMA2_S2FCR (STM32_DMA2_BASE+STM32_DMA_S2FCR_OFFSET)
+#define STM32_DMA2_S3FCR (STM32_DMA2_BASE+STM32_DMA_S3FCR_OFFSET)
+#define STM32_DMA2_S4FCR (STM32_DMA2_BASE+STM32_DMA_S4FCR_OFFSET)
+#define STM32_DMA2_S5FCR (STM32_DMA2_BASE+STM32_DMA_S5FCR_OFFSET)
+#define STM32_DMA2_S6FCR (STM32_DMA2_BASE+STM32_DMA_S6FCR_OFFSET)
+#define STM32_DMA2_S7FCR (STM32_DMA2_BASE+STM32_DMA_S7FCR_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+#define DMA_STREAM_MASK 0x3f
+#define DMA_STREAM_FEIF_BIT (1 << 0) /* Bit 0: Stream FIFO error interrupt flag */
+#define DMA_STREAM_DMEIF_BIT (1 << 2) /* Bit 2: Stream direct mode error interrupt flag */
+#define DMA_STREAM_TEIF_BIT (1 << 3) /* Bit 3: Stream Transfer Error flag */
+#define DMA_STREAM_HTIF_BIT (1 << 4) /* Bit 4: Stream Half Transfer flag */
+#define DMA_STREAM_TCIF_BIT (1 << 5) /* Bit 5: Stream Transfer Complete flag */
+
+/* DMA interrupt status register and interrupt flag clear register field defintions */
+
+#define DMA_INT_STREAM0_SHIFT (0) /* Bits 0-5: DMA Stream 0 interrupt */
+#define DMA_INT_STREAM0_MASK (DMA_STREAM_MASK << DMA_INT_STREAM0_SHIFT)
+#define DMA_INT_STREAM1_SHIFT (6) /* Bits 6-11: DMA Stream 1 interrupt */
+#define DMA_INT_STREAM1_MASK (DMA_STREAM_MASK << DMA_INT_STREAM1_SHIFT)
+#define DMA_INT_STREAM2_SHIFT (16) /* Bits 16-21: DMA Stream 2 interrupt */
+#define DMA_INT_STREAM2_MASK (DMA_STREAM_MASK << DMA_INT_STREAM2_SHIFT)
+#define DMA_INT_STREAM3_SHIFT (22) /* Bits 22-27: DMA Stream 3 interrupt */
+#define DMA_INT_STREAM3_MASK (DMA_STREAM_MASK << DMA_INT_STREAM3_SHIFT)
+
+#define DMA_INT_STREAM4_SHIFT (0) /* Bits 0-5: DMA Stream 4 interrupt */
+#define DMA_INT_STREAM4_MASK (DMA_STREAM_MASK << DMA_INT_STREAM4_SHIFT)
+#define DMA_INT_STREAM5_SHIFT (6) /* Bits 6-11: DMA Stream 5 interrupt */
+#define DMA_INT_STREAM5_MASK (DMA_STREAM_MASK << DMA_INT_STREAM5_SHIFT)
+#define DMA_INT_STREAM6_SHIFT (16) /* Bits 16-21: DMA Stream 6 interrupt */
+#define DMA_INT_STREAM6_MASK (DMA_STREAM_MASK << DMA_INT_STREAM6_SHIFT)
+#define DMA_INT_STREAM7_SHIFT (22) /* Bits 22-27: DMA Stream 7 interrupt */
+#define DMA_INT_STREAM7_MASK (DMA_STREAM_MASK << DMA_INT_STREAM7_SHIFT)
+
+/* DMA stream configuration register */
+
+#define DMA_SCR_EN (1 << 0) /* Bit 0: Stream enable */
+#define DMA_SCR_DMEIE (1 << 1) /* Bit 1: Direct mode error interrupt enable */
+#define DMA_SCR_TEIE (1 << 2) /* Bit 2: Transfer error interrupt enable */
+#define DMA_SCR_HTIE (1 << 3) /* Bit 3: Half Transfer interrupt enable */
+#define DMA_SCR_TCIE (1 << 4) /* Bit 4: Transfer complete interrupt enable */
+#define DMA_SCR_PFCTRL (1 << 5) /* Bit 5: Peripheral flow controller */
+#define DMA_SCR_DIR_SHIFT (6) /* Bits 6-7: Data transfer direction */
+#define DMA_SCR_DIR_MASK (3 << DMA_SCR_DIR_SHIFT)
+# define DMA_SCR_DIR_P2M (0 << DMA_SCR_DIR_SHIFT) /* 00: Peripheral-to-memory */
+# define DMA_SCR_DIR_M2P (1 << DMA_SCR_DIR_SHIFT) /* 01: Memory-to-peripheral */
+# define DMA_SCR_DIR_M2M (2 << DMA_SCR_DIR_SHIFT) /* 10: Memory-to-memory */
+#define DMA_SCR_CIRC (1 << 8) /* Bit 8: Circular mode */
+#define DMA_SCR_PINC (1 << 9) /* Bit 9: Peripheral increment mode */
+#define DMA_SCR_MINC (1 << 10) /* Bit 10: Memory increment mode */
+#define DMA_SCR_PSIZE_SHIFT (11) /* Bits 11-12: Peripheral size */
+#define DMA_SCR_PSIZE_MASK (3 << DMA_SCR_PSIZE_SHIFT)
+# define DMA_SCR_PSIZE_8BITS (0 << DMA_SCR_PSIZE_SHIFT) /* 00: 8-bits */
+# define DMA_SCR_PSIZE_16BITS (1 << DMA_SCR_PSIZE_SHIFT) /* 01: 16-bits */
+# define DMA_SCR_PSIZE_32BITS (2 << DMA_SCR_PSIZE_SHIFT) /* 10: 32-bits */
+#define DMA_SCR_MSIZE_SHIFT (13) /* Bits 13-14: Memory size */
+#define DMA_SCR_MSIZE_MASK (3 << DMA_SCR_MSIZE_SHIFT)
+# define DMA_SCR_MSIZE_8BITS (0 << DMA_SCR_MSIZE_SHIFT) /* 00: 8-bits */
+# define DMA_SCR_MSIZE_16BITS (1 << DMA_SCR_MSIZE_SHIFT) /* 01: 16-bits */
+# define DMA_SCR_MSIZE_32BITS (2 << DMA_SCR_MSIZE_SHIFT) /* 10: 32-bits */
+#define DMA_SCR_PINCOS (1 << 15) /* Bit 15: Peripheral increment offset size */
+#define DMA_SCR_PL_SHIFT (16) /* Bits 16-17: Stream Priority level */
+#define DMA_SCR_PL_MASK (3 << DMA_SCR_PL_SHIFT)
+# define DMA_SCR_PRILO (0 << DMA_SCR_PL_SHIFT) /* 00: Low */
+# define DMA_SCR_PRIMED (1 << DMA_SCR_PL_SHIFT) /* 01: Medium */
+# define DMA_SCR_PRIHI (2 << DMA_SCR_PL_SHIFT) /* 10: High */
+# define DMA_SCR_PRIVERYHI (3 << DMA_SCR_PL_SHIFT) /* 11: Very high */
+#define DMA_SCR_DBM (1 << 18) /* Bit 15: Double buffer mode */
+#define DMA_SCR_CT (1 << 19) /* Bit 19: Current target */
+#define DMA_SCR_PBURST_SHIFT (21) /* Bits 21-22: Peripheral burst transfer configuration */
+#define DMA_SCR_PBURST_MASK (3 << DMA_SCR_PBURST_SHIFT)
+# define DMA_SCR_PBURST_SINGLE (0 << DMA_SCR_PBURST_SHIFT) /* 00: Single transfer */
+# define DMA_SCR_PBURST_INCR4 (1 << DMA_SCR_PBURST_SHIFT) /* 01: Incremental burst of 4 beats */
+# define DMA_SCR_PBURST_INCR8 (2 << DMA_SCR_PBURST_SHIFT) /* 10: Incremental burst of 8 beats */
+# define DMA_SCR_PBURST_INCR16 (3 << DMA_SCR_PBURST_SHIFT) /* 11: Incremental burst of 16 beats */
+#define DMA_SCR_MBURST_SHIFT (23) /* Bits 23-24: Memory burst transfer configuration */
+#define DMA_SCR_MBURST_MASK (3 << DMA_SCR_MBURST_SHIFT)
+# define DMA_SCR_MBURST_SINGLE (0 << DMA_SCR_MBURST_SHIFT) /* 00: Single transfer */
+# define DMA_SCR_MBURST_INCR4 (1 << DMA_SCR_MBURST_SHIFT) /* 01: Incremental burst of 4 beats */
+# define DMA_SCR_MBURST_INCR8 (2 << DMA_SCR_MBURST_SHIFT) /* 10: Incremental burst of 8 beats */
+# define DMA_SCR_MBURST_INCR16 (3 << DMA_SCR_MBURST_SHIFT) /* 11: Incremental burst of 16 beats */
+#define DMA_SCR_CHSEL_SHIFT (25) /* Bits 25-27: Channel selection */
+#define DMA_SCR_CHSEL_MASK (7 << DMA_SCR_CHSEL_SHIFT)
+# define DMA_SCR_CHSEL(n) ((n) << DMA_SCR_CHSEL_SHIFT)
+
+#define DMA_SCR_ALLINTS (DMA_SCR_DMEIE|DMA_SCR_TEIE|DMA_SCR_HTIE|DMA_SCR_TCIE)
+
+/* DMA stream number of data register */
+
+#define DMA_SNDTR_NDT_SHIFT (0) /* Bits 15-0: Number of data to Transfer */
+#define DMA_SNDTR_NDT_MASK (0xffff << DMA_SNDTR_NDT_SHIFT)
+
+/* DMA stream n FIFO control register */
+
+#define DMA_SFCR_FTH_SHIFT (0) /* Bits 0-1: FIFO threshold selection */
+#define DMA_SFCR_FTH_MASK (3 << DMA_SFCR_FTH_SHIFT)
+# define DMA_SFCR_FTH_QUARTER (0 << DMA_SFCR_FTH_SHIFT) /* 1/4 full FIFO */
+# define DMA_SFCR_FTH_HALF (1 << DMA_SFCR_FTH_SHIFT) /* 1/2 full FIFO */
+# define DMA_SFCR_FTH_3QUARTER (2 << DMA_SFCR_FTH_SHIFT) /* 3/4 full FIFO */
+# define DMA_SFCR_FTH_FULL (3 << DMA_SFCR_FTH_SHIFT) /* full FIFO */
+#define DMA_SFCR_DMDIS (1 << 2) /* Bit 2: Direct mode disable */
+#define DMA_SFCR_FS_SHIFT (3) /* Bits 3-5: FIFO status */
+#define DMA_SFCR_FS_MASK (7 << DMA_SFCR_FS_SHIFT)
+# define DMA_SFCR_FS_QUARTER (0 << DMA_SFCR_FS_SHIFT) /* 0 < fifo_level < 1/4 */
+# define DMA_SFCR_FS_HALF (1 << DMA_SFCR_FS_SHIFT) /* 1/4 = fifo_level < 1/2 */
+# define DMA_SFCR_FS_3QUARTER (2 << DMA_SFCR_FS_SHIFT) /* 1/2 = fifo_level < 3/4 */
+# define DMA_SFCR_FS_ALMOSTFULL (3 << DMA_SFCR_FS_SHIFT) /* 3/4 = fifo_level < full */
+# define DMA_SFCR_FS_EMPTY (4 << DMA_SFCR_FS_SHIFT) /* FIFO is empty */
+# define DMA_SFCR_FS_FULL (5 << DMA_SFCR_FS_SHIFT) /* FIFO is full */
+ /* Bit 6: Reserved */
+#define DMA_SFCR_FEIE (1 << 7) /* Bit 7: FIFO error interrupt enable */
+ /* Bits 8-31: Reserved */
+
+/* DMA Stream mapping. Each DMA stream has a mapping to several possible
+ * sources/sinks of data. The requests from peripherals assigned to a stream
+ * are simply OR'ed together before entering the DMA block. This means that only
+ * one request on a given stream can be enabled at once.
+ *
+ * Alternative stream selections are provided with a numeric suffix like _1, _2, etc.
+ * The DMA driver, however, will use the pin selection without the numeric suffix.
+ * Additional definitions are required in the board.h file. For example, if
+ * SPI3_RX connects via DMA STREAM0, then following should be application-specific
+ * mapping should be used:
+ *
+ * #define DMAMAP_SPI3_RX DMAMAP_SPI3_RX_1
+ */
+
+#define STM32_DMA_MAP(d,s,c) ((d) << 6 | (s) << 3 | (c))
+#define STM32_DMA_CONTROLLER(m) (((m) >> 6) & 1)
+#define STM32_DMA_STREAM(m) (((m) >> 3) & 7)
+#define STM32_DMA_CHANNEL(m) ((m) & 7)
+
+#define DMAMAP_SPI3_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN0)
+#define DMAMAP_SPI3_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN0)
+#define DMAMAP_SPI2_RX STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN0)
+#define DMAMAP_SPI2_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN0)
+#define DMAMAP_SPI3_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN0)
+#define DMAMAP_SPI3_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN0)
+
+#define DMAMAP_I2C1_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN1)
+#define DMAMAP_TIM7_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN1)
+#define DMAMAP_TIM7_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN1)
+#define DMAMAP_I2C1_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN1)
+#define DMAMAP_I2C1_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN1)
+#define DMAMAP_I2C1_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN1)
+
+#define DMAMAP_TIM4_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN2)
+#define DMAMAP_I2S2_EXT_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN2)
+#define DMAMAP_TIM4_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN2)
+#define DMAMAP_I2S2_EXT_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN2)
+#define DMAMAP_I2S3_EXT_TX STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN2)
+#define DMAMAP_TIM4_UP STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN2)
+#define DMAMAP_TIM4_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN2)
+
+#define DMAMAP_I2S3_EXT_RX STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN3)
+#define DMAMAP_TIM2_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN3)
+#define DMAMAP_TIM2_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN3)
+#define DMAMAP_I2C3_RX STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN3)
+#define DMAMAP_I2S2_EXT_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN3)
+#define DMAMAP_I2C3_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN3)
+#define DMAMAP_TIM2_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN3)
+#define DMAMAP_TIM2_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN3)
+#define DMAMAP_TIM2_CH4_1 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN3)
+#define DMAMAP_TIM2_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN3)
+#define DMAMAP_TIM2_CH4_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN3)
+
+#define DMAMAP_UART5_RX STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN4)
+#define DMAMAP_USART3_RX STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN4)
+#define DMAMAP_UART4_RX STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN4)
+#define DMAMAP_USART3_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN4)
+#define DMAMAP_UART4_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN4)
+#define DMAMAP_USART2_RX STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN4)
+#define DMAMAP_USART2_TX STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN4)
+#define DMAMAP_UART5_TX STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN4)
+
+#define DMAMAP_TIM3_CH4 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN5)
+#define DMAMAP_TIM3_UP STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN5)
+#define DMAMAP_TIM3_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN5)
+#define DMAMAP_TIM3_TRIG STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN5)
+#define DMAMAP_TIM3_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN5)
+#define DMAMAP_TIM3_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN5)
+
+#define DMAMAP_TIM5_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN6)
+#define DMAMAP_TIM5_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN6)
+#define DMAMAP_TIM5_CH4_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN6)
+#define DMAMAP_TIM5_TRIG_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN6)
+#define DMAMAP_TIM5_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN6)
+#define DMAMAP_TIM5_CH4_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN6)
+#define DMAMAP_TIM5_TRIG_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN6)
+#define DMAMAP_TIM5_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN6)
+#define DMAMAP_TIM5_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN6)
+
+#define DMAMAP_TIM6_UP STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN7)
+#define DMAMAP_I2C2_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN7)
+#define DMAMAP_I2C2_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN7)
+#define DMAMAP_USART3_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN7)
+#define DMAMAP_DAC1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN7)
+#define DMAMAP_DAC2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN7)
+#define DMAMAP_I2C2_TX STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN7)
+
+#define DMAMAP_ADC1_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN0)
+#define DMAMAP_TIM8_CH1_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0)
+#define DMAMAP_TIM8_CH2_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0)
+#define DMAMAP_TIM8_CH3_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0)
+#define DMAMAP_ADC1_2 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN0)
+#define DMAMAP_TIM1_CH1_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0)
+#define DMAMAP_TIM1_CH2_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0)
+#define DMAMAP_TIM1_CH3_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0)
+
+#define DMAMAP_DCMI_1 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN1)
+#define DMAMAP_ADC2_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN1)
+#define DMAMAP_ADC2_2 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN1)
+#define DMAMAP_DCMI_2 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN1)
+
+#define DMAMAP_ADC3_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN2)
+#define DMAMAP_ADC3_2 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN2)
+#define DMAMAP_CRYP_OUT STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN2)
+#define DMAMAP_CRYP_IN STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN2)
+#define DMAMAP_HASH_IN STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN2)
+
+#define DMAMAP_SPI1_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN3)
+#define DMAMAP_SPI1_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN3)
+#define DMAMAP_SPI1_TX_1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN3)
+#define DMAMAP_SPI1_TX_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN3)
+
+#define DMAMAP_USART1_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN4)
+#define DMAMAP_SDIO_1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN4)
+#define DMAMAP_USART1_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN4)
+#define DMAMAP_SDIO_2 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN4)
+#define DMAMAP_USART1_TX STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN4)
+
+#define DMAMAP_USART6_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN5)
+#define DMAMAP_USART6_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN5)
+#define DMAMAP_USART6_TX_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN5)
+#define DMAMAP_USART6_TX_2 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN5)
+
+#define DMAMAP_TIM1_TRIG_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN6)
+#define DMAMAP_TIM1_CH1_2 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN6)
+#define DMAMAP_TIM1_CH2_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN6)
+#define DMAMAP_TIM1_CH1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN6)
+#define DMAMAP_TIM1_CH4 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6)
+#define DMAMAP_TIM1_TRIG_2 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6)
+#define DMAMAP_TIM1_COM STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6)
+#define DMAMAP_TIM1_UP STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN6)
+#define DMAMAP_TIM1_CH3_2 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN6)
+
+#define DMAMAP_TIM8_UP STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN7)
+#define DMAMAP_TIM8_CH1_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN7)
+#define DMAMAP_TIM8_CH2_2 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN7)
+#define DMAMAP_TIM8_CH3_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN7)
+#define DMAMAP_TIM8_CH4 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7)
+#define DMAMAP_TIM8_TRIG STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7)
+#define DMAMAP_TIM8_COM STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_DMA_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_gpio.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_gpio.h
new file mode 100644
index 000000000..73a028244
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_gpio.h
@@ -0,0 +1,370 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f20xxx_gpio.h
+ *
+ * Copyright (C) 2012 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_STM32_CHIP_STM32F20XXX_GPIO_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_GPIO_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#define STM32_NGPIO_PORTS ((STM32_NGPIO + 15) >> 4)
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_GPIO_MODER_OFFSET 0x0000 /* GPIO port mode register */
+#define STM32_GPIO_OTYPER_OFFSET 0x0004 /* GPIO port output type register */
+#define STM32_GPIO_OSPEED_OFFSET 0x0008 /* GPIO port output speed register */
+#define STM32_GPIO_PUPDR_OFFSET 0x000c /* GPIO port pull-up/pull-down register */
+#define STM32_GPIO_IDR_OFFSET 0x0010 /* GPIO port input data register */
+#define STM32_GPIO_ODR_OFFSET 0x0014 /* GPIO port output data register */
+#define STM32_GPIO_BSRR_OFFSET 0x0018 /* GPIO port bit set/reset register */
+#define STM32_GPIO_LCKR_OFFSET 0x001c /* GPIO port configuration lock register */
+#define STM32_GPIO_AFRL_OFFSET 0x0020 /* GPIO alternate function low register */
+#define STM32_GPIO_ARFH_OFFSET 0x0024 /* GPIO alternate function high register */
+
+/* Register Addresses ***************************************************************/
+
+#if STM32_NGPIO_PORTS > 0
+# define STM32_GPIOA_MODER (STM32_GPIOA_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOA_OTYPER (STM32_GPIOA_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOA_OSPEED (STM32_GPIOA_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOA_PUPDR (STM32_GPIOA_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOA_IDR (STM32_GPIOA_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOA_ODR (STM32_GPIOA_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOA_BSRR (STM32_GPIOA_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOA_LCKR (STM32_GPIOA_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOA_AFRL (STM32_GPIOA_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOA_ARFH (STM32_GPIOA_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 1
+# define STM32_GPIOB_MODER (STM32_GPIOB_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOB_OTYPER (STM32_GPIOB_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOB_OSPEED (STM32_GPIOB_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOB_PUPDR (STM32_GPIOB_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOB_IDR (STM32_GPIOB_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOB_ODR (STM32_GPIOB_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOB_BSRR (STM32_GPIOB_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOB_LCKR (STM32_GPIOB_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOB_AFRL (STM32_GPIOB_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOB_ARFH (STM32_GPIOB_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 2
+# define STM32_GPIOC_MODER (STM32_GPIOC_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOC_OTYPER (STM32_GPIOC_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOC_OSPEED (STM32_GPIOC_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOC_PUPDR (STM32_GPIOC_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOC_IDR (STM32_GPIOC_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOC_ODR (STM32_GPIOC_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOC_BSRR (STM32_GPIOC_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOC_LCKR (STM32_GPIOC_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOC_AFRL (STM32_GPIOC_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOC_ARFH (STM32_GPIOC_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 3
+# define STM32_GPIOD_MODER (STM32_GPIOD_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOD_OTYPER (STM32_GPIOD_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOD_OSPEED (STM32_GPIOD_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOD_PUPDR (STM32_GPIOD_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOD_IDR (STM32_GPIOD_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOD_ODR (STM32_GPIOD_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOD_BSRR (STM32_GPIOD_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOD_LCKR (STM32_GPIOD_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOD_AFRL (STM32_GPIOD_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOD_ARFH (STM32_GPIOD_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 4
+# define STM32_GPIOE_MODER (STM32_GPIOE_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOE_OTYPER (STM32_GPIOE_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOE_OSPEED (STM32_GPIOE_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOE_PUPDR (STM32_GPIOE_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOE_IDR (STM32_GPIOE_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOE_ODR (STM32_GPIOE_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOE_BSRR (STM32_GPIOE_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOE_LCKR (STM32_GPIOE_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOE_AFRL (STM32_GPIOE_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOE_ARFH (STM32_GPIOE_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 5
+# define STM32_GPIOF_MODER (STM32_GPIOF_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOF_OTYPER (STM32_GPIOF_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOF_OSPEED (STM32_GPIOF_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOF_PUPDR (STM32_GPIOF_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOF_IDR (STM32_GPIOF_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOF_ODR (STM32_GPIOF_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOF_BSRR (STM32_GPIOF_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOF_LCKR (STM32_GPIOF_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOF_AFRL (STM32_GPIOF_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOF_ARFH (STM32_GPIOF_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 6
+# define STM32_GPIOG_MODER (STM32_GPIOG_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOG_OTYPER (STM32_GPIOG_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOG_OSPEED (STM32_GPIOG_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOG_PUPDR (STM32_GPIOG_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOG_IDR (STM32_GPIOG_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOG_ODR (STM32_GPIOG_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOG_BSRR (STM32_GPIOG_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOG_LCKR (STM32_GPIOG_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOG_AFRL (STM32_GPIOG_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOG_ARFH (STM32_GPIOG_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 7
+# define STM32_GPIOH_MODER (STM32_GPIOH_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOH_OTYPER (STM32_GPIOH_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOH_OSPEED (STM32_GPIOH_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOH_PUPDR (STM32_GPIOH_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOH_IDR (STM32_GPIOH_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOH_ODR (STM32_GPIOH_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOH_BSRR (STM32_GPIOH_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOH_LCKR (STM32_GPIOH_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOH_AFRL (STM32_GPIOH_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOH_ARFH (STM32_GPIOH_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 8
+# define STM32_GPIOI_MODER (STM32_GPIOI_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOI_OTYPER (STM32_GPIOI_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOI_OSPEED (STM32_GPIOI_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOI_PUPDR (STM32_GPIOI_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOI_IDR (STM32_GPIOI_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOI_ODR (STM32_GPIOI_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOI_BSRR (STM32_GPIOI_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOI_LCKR (STM32_GPIOI_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOI_AFRL (STM32_GPIOI_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOI_ARFH (STM32_GPIOI_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* GPIO port mode register */
+
+#define GPIO_MODER_INPUT (0) /* Input */
+#define GPIO_MODER_OUTPUT (1) /* General purpose output mode */
+#define GPIO_MODER_ALT (2) /* Alternate mode */
+#define GPIO_MODER_ANALOG (3) /* Analog mode */
+
+#define GPIO_MODER_SHIFT(n) ((n) << 1)
+#define GPIO_MODER_MASK(n) (3 << GPIO_MODER_SHIFT(n))
+
+#define GPIO_MODER0_SHIFT (0)
+#define GPIO_MODER0_MASK (3 << GPIO_MODER0_SHIFT)
+#define GPIO_MODER1_SHIFT (2)
+#define GPIO_MODER1_MASK (3 << GPIO_MODER1_SHIFT)
+#define GPIO_MODER2_SHIFT (4)
+#define GPIO_MODER2_MASK (3 << GPIO_MODER2_SHIFT)
+#define GPIO_MODER3_SHIFT (6)
+#define GPIO_MODER3_MASK (3 << GPIO_MODER3_SHIFT)
+#define GPIO_MODER4_SHIFT (8)
+#define GPIO_MODER4_MASK (3 << GPIO_MODER4_SHIFT)
+#define GPIO_MODER5_SHIFT (10)
+#define GPIO_MODER5_MASK (3 << GPIO_MODER5_SHIFT)
+#define GPIO_MODER6_SHIFT (12)
+#define GPIO_MODER6_MASK (3 << GPIO_MODER6_SHIFT)
+#define GPIO_MODER7_SHIFT (14)
+#define GPIO_MODER7_MASK (3 << GPIO_MODER7_SHIFT)
+#define GPIO_MODER8_SHIFT (16)
+#define GPIO_MODER8_MASK (3 << GPIO_MODER8_SHIFT)
+#define GPIO_MODER9_SHIFT (18)
+#define GPIO_MODER9_MASK (3 << GPIO_MODER9_SHIFT)
+#define GPIO_MODER10_SHIFT (20)
+#define GPIO_MODER10_MASK (3 << GPIO_MODER10_SHIFT)
+#define GPIO_MODER11_SHIFT (22)
+#define GPIO_MODER11_MASK (3 << GPIO_MODER11_SHIFT)
+#define GPIO_MODER12_SHIFT (24)
+#define GPIO_MODER12_MASK (3 << GPIO_MODER12_SHIFT)
+#define GPIO_MODER13_SHIFT (26)
+#define GPIO_MODER13_MASK (3 << GPIO_MODER13_SHIFT)
+#define GPIO_MODER14_SHIFT (28)
+#define GPIO_MODER14_MASK (3 << GPIO_MODER14_SHIFT)
+#define GPIO_MODER15_SHIFT (30)
+#define GPIO_MODER15_MASK (3 << GPIO_MODER15_SHIFT)
+
+/* GPIO port output type register */
+
+#define GPIO_OTYPER_OD(n) (1 << (n)) /* 1=Output open-drain */
+#define GPIO_OTYPER_PP(n) (0) /* 0=Ouput push-pull */
+
+/* GPIO port output speed register */
+
+#define GPIO_OSPEED_2MHz (0) /* 2 MHz Low speed */
+#define GPIO_OSPEED_25MHz (1) /* 25 MHz Medium speed */
+#define GPIO_OSPEED_50MHz (2) /* 50 MHz Fast speed */
+#define GPIO_OSPEED_100MHz (3) /* 100 MHz High speed on 30 pF (80 MHz Output max speed on 15 pF) */
+
+#define GPIO_OSPEED_SHIFT(n) ((n) << 1)
+#define GPIO_OSPEED_MASK(n) (3 << GPIO_OSPEED_SHIFT(n))
+
+#define GPIO_OSPEED0_SHIFT (0)
+#define GPIO_OSPEED0_MASK (3 << GPIO_OSPEED0_SHIFT)
+#define GPIO_OSPEED1_SHIFT (2)
+#define GPIO_OSPEED1_MASK (3 << GPIO_OSPEED1_SHIFT)
+#define GPIO_OSPEED2_SHIFT (4)
+#define GPIO_OSPEED2_MASK (3 << GPIO_OSPEED2_SHIFT)
+#define GPIO_OSPEED3_SHIFT (6)
+#define GPIO_OSPEED3_MASK (3 << GPIO_OSPEED3_SHIFT)
+#define GPIO_OSPEED4_SHIFT (8)
+#define GPIO_OSPEED4_MASK (3 << GPIO_OSPEED4_SHIFT)
+#define GPIO_OSPEED5_SHIFT (10)
+#define GPIO_OSPEED5_MASK (3 << GPIO_OSPEED5_SHIFT)
+#define GPIO_OSPEED6_SHIFT (12)
+#define GPIO_OSPEED6_MASK (3 << GPIO_OSPEED6_SHIFT)
+#define GPIO_OSPEED7_SHIFT (14)
+#define GPIO_OSPEED7_MASK (3 << GPIO_OSPEED7_SHIFT)
+#define GPIO_OSPEED8_SHIFT (16)
+#define GPIO_OSPEED8_MASK (3 << GPIO_OSPEED8_SHIFT)
+#define GPIO_OSPEED9_SHIFT (18)
+#define GPIO_OSPEED9_MASK (3 << GPIO_OSPEED9_SHIFT)
+#define GPIO_OSPEED10_SHIFT (20)
+#define GPIO_OSPEED10_MASK (3 << GPIO_OSPEED10_SHIFT)
+#define GPIO_OSPEED11_SHIFT (22)
+#define GPIO_OSPEED11_MASK (3 << GPIO_OSPEED11_SHIFT)
+#define GPIO_OSPEED12_SHIFT (24)
+#define GPIO_OSPEED12_MASK (3 << GPIO_OSPEED12_SHIFT)
+#define GPIO_OSPEED13_SHIFT (26)
+#define GPIO_OSPEED13_MASK (3 << GPIO_OSPEED13_SHIFT)
+#define GPIO_OSPEED14_SHIFT (28)
+#define GPIO_OSPEED14_MASK (3 << GPIO_OSPEED14_SHIFT)
+#define GPIO_OSPEED15_SHIFT (30)
+#define GPIO_OSPEED15_MASK (3 << GPIO_OSPEED15_SHIFT)
+
+/* GPIO port pull-up/pull-down register */
+
+#define GPIO_PUPDR_NONE (0) /* No pull-up, pull-down */
+#define GPIO_PUPDR_PULLUP (1) /* Pull-up */
+#define GPIO_PUPDR_PULLDOWN (2) /* Pull-down */
+
+#define GPIO_PUPDR_SHIFT(n) ((n) << 1)
+#define GPIO_PUPDR_MASK(n) (3 << GPIO_PUPDR_SHIFT(n))
+
+#define GPIO_PUPDR0_SHIFT (0)
+#define GPIO_PUPDR0_MASK (3 << GPIO_PUPDR0_SHIFT)
+#define GPIO_PUPDR1_SHIFT (2)
+#define GPIO_PUPDR1_MASK (3 << GPIO_PUPDR1_SHIFT)
+#define GPIO_PUPDR2_SHIFT (4)
+#define GPIO_PUPDR2_MASK (3 << GPIO_PUPDR2_SHIFT)
+#define GPIO_PUPDR3_SHIFT (6)
+#define GPIO_PUPDR3_MASK (3 << GPIO_PUPDR3_SHIFT)
+#define GPIO_PUPDR4_SHIFT (8)
+#define GPIO_PUPDR4_MASK (3 << GPIO_PUPDR4_SHIFT)
+#define GPIO_PUPDR5_SHIFT (10)
+#define GPIO_PUPDR5_MASK (3 << GPIO_PUPDR5_SHIFT)
+#define GPIO_PUPDR6_SHIFT (12)
+#define GPIO_PUPDR6_MASK (3 << GPIO_PUPDR6_SHIFT)
+#define GPIO_PUPDR7_SHIFT (14)
+#define GPIO_PUPDR7_MASK (3 << GPIO_PUPDR7_SHIFT)
+#define GPIO_PUPDR8_SHIFT (16)
+#define GPIO_PUPDR8_MASK (3 << GPIO_PUPDR8_SHIFT)
+#define GPIO_PUPDR9_SHIFT (18)
+#define GPIO_PUPDR9_MASK (3 << GPIO_PUPDR9_SHIFT)
+#define GPIO_PUPDR10_SHIFT (20)
+#define GPIO_PUPDR10_MASK (3 << GPIO_PUPDR10_SHIFT)
+#define GPIO_PUPDR11_SHIFT (22)
+#define GPIO_PUPDR11_MASK (3 << GPIO_PUPDR11_SHIFT)
+#define GPIO_PUPDR12_SHIFT (24)
+#define GPIO_PUPDR12_MASK (3 << GPIO_PUPDR12_SHIFT)
+#define GPIO_PUPDR13_SHIFT (26)
+#define GPIO_PUPDR13_MASK (3 << GPIO_PUPDR13_SHIFT)
+#define GPIO_PUPDR14_SHIFT (28)
+#define GPIO_PUPDR14_MASK (3 << GPIO_PUPDR14_SHIFT)
+#define GPIO_PUPDR15_SHIFT (30)
+#define GPIO_PUPDR15_MASK (3 << GPIO_PUPDR15_SHIFT)
+
+/* GPIO port input data register */
+
+#define GPIO_IDR(n) (1 << (n))
+
+/* GPIO port output data register */
+
+#define GPIO_ODR(n) (1 << (n))
+
+/* GPIO port bit set/reset register */
+
+#define GPIO_BSRR_SET(n) (1 << (n))
+#define GPIO_BSRR_RESET(n) (1 << ((n)+16))
+
+/* GPIO port configuration lock register */
+
+#define GPIO_LCKR(n) (1 << (n))
+#define GPIO_LCKK (1 << 16) /* Lock key */
+
+/* GPIO alternate function low/high register */
+
+#define GPIO_AFR_SHIFT(n) ((n) << 2)
+#define GPIO_AFR_MASK(n) (15 << GPIO_AFR_SHIFT(n))
+
+#define GPIO_AFRL0_SHIFT (0)
+#define GPIO_AFRL0_MASK (15 << GPIO_AFRL0_SHIFT)
+#define GPIO_AFRL1_SHIFT (4)
+#define GPIO_AFRL1_MASK (15 << GPIO_AFRL1_SHIFT)
+#define GPIO_AFRL2_SHIFT (8)
+#define GPIO_AFRL2_MASK (15 << GPIO_AFRL2_SHIFT)
+#define GPIO_AFRL3_SHIFT (12)
+#define GPIO_AFRL3_MASK (15 << GPIO_AFRL3_SHIFT)
+#define GPIO_AFRL4_SHIFT (16)
+#define GPIO_AFRL4_MASK (15 << GPIO_AFRL4_SHIFT)
+#define GPIO_AFRL5_SHIFT (20)
+#define GPIO_AFRL5_MASK (15 << GPIO_AFRL5_SHIFT)
+#define GPIO_AFRL6_SHIFT (24)
+#define GPIO_AFRL6_MASK (15 << GPIO_AFRL6_SHIFT)
+#define GPIO_AFRL7_SHIFT (28)
+#define GPIO_AFRL7_MASK (15 << GPIO_AFRL7_SHIFT)
+
+#define GPIO_AFRH8_SHIFT (0)
+#define GPIO_AFRH8_MASK (15 << GPIO_AFRH8_SHIFT)
+#define GPIO_AFRH9_SHIFT (4)
+#define GPIO_AFRH9_MASK (15 << GPIO_AFRH9_SHIFT)
+#define GPIO_AFRH10_SHIFT (8)
+#define GPIO_AFRH10_MASK (15 << GPIO_AFRH10_SHIFT)
+#define GPIO_AFRH11_SHIFT (12)
+#define GPIO_AFRH11_MASK (15 << GPIO_AFRH11_SHIFT)
+#define GPIO_AFRH12_SHIFT (16)
+#define GPIO_AFRH12_MASK (15 << GPIO_AFRH12_SHIFT)
+#define GPIO_AFRH13_SHIFT (20)
+#define GPIO_AFRH13_MASK (15 << GPIO_AFRH13_SHIFT)
+#define GPIO_AFRH14_SHIFT (24)
+#define GPIO_AFRH14_MASK (15 << GPIO_AFRH14_SHIFT)
+#define GPIO_AFRH15_SHIFT (28)
+#define GPIO_AFRH15_MASK (15 << GPIO_AFRH15_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_GPIO_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_memorymap.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_memorymap.h
new file mode 100644
index 000000000..2fa705607
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_memorymap.h
@@ -0,0 +1,197 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f20xxx_memorymap.h
+ *
+ * Copyright (C) 2012 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_STM32_CHIP_STM32F20XXX_MEMORYMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_MEMORYMAP_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* STM32F20XXX Address Blocks *******************************************************/
+
+#define STM32_CODE_BASE 0x00000000 /* 0x00000000-0x1fffffff: 512Mb code block */
+#define STM32_SRAM_BASE 0x20000000 /* 0x20000000-0x3fffffff: 512Mb sram block */
+#define STM32_PERIPH_BASE 0x40000000 /* 0x40000000-0x5fffffff: 512Mb peripheral block */
+#define STM32_FSMC_BASE12 0x60000000 /* 0x60000000-0x7fffffff: 512Mb FSMC bank1&2 block */
+#define STM32_FSMC_BASE34 0x80000000 /* 0x80000000-0x8fffffff: 512Mb FSMC bank3&4 block */
+#define STM32_FSMC_BASE 0xa0000000 /* 0xa0000000-0xbfffffff: 512Mb FSMC register block */
+ /* 0xc0000000-0xdfffffff: 512Mb (not used) */
+#define STM32_CORTEX_BASE 0xe0000000 /* 0xe0000000-0xffffffff: 512Mb Cortex-M4 block */
+
+/* Code Base Addresses **************************************************************/
+
+#define STM32_BOOT_BASE 0x00000000 /* 0x00000000-0x000fffff: Aliased boot memory */
+ /* 0x00100000-0x07ffffff: Reserved */
+#define STM32_FLASH_BASE 0x08000000 /* 0x08000000-0x080fffff: FLASH memory */
+ /* 0x08100000-0x0fffffff: Reserved */
+#define STM32_CCMRAM_BASE 0x10000000 /* 0x10000000-0x1000ffff: 64Kb CCM data RAM */
+ /* 0x10010000-0x1ffeffff: Reserved */
+#define STM32_SYSMEM_BASE 0x1fff0000 /* 0x1fff0000-0x1fff7a0f: System memory */
+ /* 0x1fff7a10-0x1fff7fff: Reserved */
+#define STM32_OPTION_BASE 0x1fffc000 /* 0x1fffc000-0x1fffc007: Option bytes */
+ /* 0x1fffc008-0x1fffffff: Reserved */
+
+/* SRAM Base Addresses **************************************************************/
+
+ /* 0x20000000-0x2001bfff: 112Kb aliased by bit-banding */
+ /* 0x2001c000-0x2001ffff: 16Kb aliased by bit-banding */
+#define STM32_SRAMBB_BASE 0x22000000 /* 0x22000000- : SRAM bit-band region */
+
+/* Peripheral Base Addresses ********************************************************/
+
+#define STM32_APB1_BASE 0x40000000 /* 0x40000000-0x400023ff: APB1 */
+ /* 0x40002400-0x400027ff: Reserved */
+ /* 0x40002800-0x400077ff: APB1 */
+ /* 0x40007800-0x4000ffff: Reserved */
+#define STM32_APB2_BASE 0x40010000 /* 0x40010000-0x400023ff: APB2 */
+ /* 0x40013400-0x400137ff: Reserved */
+ /* 0x40013800-0x40013bff: SYSCFG */
+#define STM32_EXTI_BASE 0x40013c00 /* 0x40013c00-0x40013fff: EXTI */
+ /* 0x40014000-0x40014bff: APB2 */
+ /* 0x40014c00-0x4001ffff: Reserved */
+#define STM32_AHB1_BASE 0x40020000 /* 0x40020000-0x400223ff: APB1 */
+ /* 0x40022400-0x40022fff: Reserved */
+ /* 0x40023000-0x400233ff: CRC */
+ /* 0x40023400-0x400237ff: Reserved */
+ /* 0x40023800-0x40023bff: Reset and Clock control RCC */
+ /* 0x40023c00-0x400293ff: AHB1 (?) */
+ /* 0x40029400-0x4fffffff: Reserved (?) */
+#define STM32_AHB2_BASE 0x50000000 /* 0x50000000-0x5003ffff: AHB2 */
+ /* 0x50040000-0x5004ffff: Reserved */
+ /* 0x50050000-0x500503ff: AHB2 */
+ /* 0x50050400-0x500607ff: Reserved */
+ /* 0x50060800-0x50060bff: AHB2 */
+ /* 0x50060c00-0x5fffffff: Reserved */
+
+/* FSMC Base Addresses **************************************************************/
+
+#define STM32_AHB3_BASE 0x60000000 /* 0x60000000-0xa0000fff: AHB3 */
+
+/* APB1 Base Addresses **************************************************************/
+
+#define STM32_TIM2_BASE 0x40000000 /* 0x40000000-0x400003ff: TIM2 timer */
+#define STM32_TIM3_BASE 0x40000400 /* 0x40000400-0x400007ff: TIM3 timer */
+#define STM32_TIM4_BASE 0x40000800 /* 0x40000800-0x40000bff: TIM4 timer */
+#define STM32_TIM5_BASE 0x40000c00 /* 0x40000c00-0x40000fff: TIM5 timer */
+#define STM32_TIM6_BASE 0x40001000 /* 0x40001000-0x400013ff: TIM6 timer */
+#define STM32_TIM7_BASE 0x40001400 /* 0x40001400-0x400017ff: TIM7 timer */
+#define STM32_TIM12_BASE 0x40001800 /* 0x40001800-0x40001bff: TIM12 timer */
+#define STM32_TIM13_BASE 0x40001c00 /* 0x40001c00-0x40001fff: TIM13 timer */
+#define STM32_TIM14_BASE 0x40002000 /* 0x40002000-0x400023ff: TIM14 timer */
+#define STM32_RTC_BASE 0x40002800 /* 0x40002800-0x40002bff: RTC & BKP registers */
+#define STM32_BKP_BASE 0x40002850
+#define STM32_WWDG_BASE 0x40002c00 /* 0x40002c00-0x40002fff: Window watchdog (WWDG) */
+#define STM32_IWDG_BASE 0x40003000 /* 0x40003000-0x400033ff: Independent watchdog (IWDG) */
+#define STM32_I2S2EXT_BASE 0x40003400 /* 0x40003400-0x400037ff: I2S2ext */
+#define STM32_SPI2_BASE 0x40003800 /* 0x40003800-0x40003bff: SPI2/I2S2 */
+#define STM32_I2S2_BASE 0x40003800
+#define STM32_SPI3_BASE 0x40003c00 /* 0x40003c00-0x40003fff: SPI3/I2S3 */
+#define STM32_I2S3_BASE 0x40003c00
+#define STM32_I2S3EXT_BASE 0x40004000 /* 0x40003400-0x400043ff: I2S3ext */
+#define STM32_USART2_BASE 0x40004400 /* 0x40004400-0x400047ff: USART2 */
+#define STM32_USART3_BASE 0x40004800 /* 0x40004800-0x40004bff: USART3 */
+#define STM32_UART4_BASE 0x40004c00 /* 0x40004c00-0x40004fff: UART4 */
+#define STM32_UART5_BASE 0x40005000 /* 0x40005000-0x400053ff: UART5 */
+#define STM32_I2C1_BASE 0x40005400 /* 0x40005400-0x400057ff: I2C1 */
+#define STM32_I2C2_BASE 0x40005800 /* 0x40005800-0x40005Bff: I2C2 */
+#define STM32_I2C3_BASE 0x40005c00 /* 0x40005c00-0x40005fff: I2C3 */
+#define STM32_CAN1_BASE 0x40006400 /* 0x40006400-0x400067ff: bxCAN1 */
+#define STM32_CAN2_BASE 0x40006800 /* 0x40006800-0x40006bff: bxCAN2 */
+#define STM32_PWR_BASE 0x40007000 /* 0x40007000-0x400073ff: Power control PWR */
+#define STM32_DAC_BASE 0x40007400 /* 0x40007400-0x400077ff: DAC */
+
+/* APB2 Base Addresses **************************************************************/
+
+#define STM32_TIM1_BASE 0x40010000 /* 0x40010000-0x400103ff: TIM1 timer */
+#define STM32_TIM8_BASE 0x40010400 /* 0x40010400-0x400107ff: TIM8 timer */
+#define STM32_USART1_BASE 0x40011000 /* 0x40011000-0x400113ff: USART1 */
+#define STM32_USART6_BASE 0x40011400 /* 0x40011400-0x400117ff: USART6 */
+#define STM32_ADC_BASE 0x40012000 /* 0x40012000-0x400123ff: ADC1-3 */
+# define STM32_ADC1_BASE 0x40012000 /* ADC1 */
+# define STM32_ADC2_BASE 0x40012100 /* ADC2 */
+# define STM32_ADC3_BASE 0x40012200 /* ADC3 */
+# define STM32_ADCCMN_BASE 0x40012300 /* Common */
+#define STM32_SDIO_BASE 0x40012c00 /* 0x40012c00-0x40012fff: SDIO */
+#define STM32_SPI1_BASE 0x40013000 /* 0x40013000-0x400133ff: SPI1 */
+#define STM32_SYSCFG_BASE 0x40013800 /* 0x40013800-0x40013bff: SYSCFG */
+#define STM32_EXTI_BASE 0x40013c00 /* 0x40013c00-0x40013fff: EXTI */
+#define STM32_TIM9_BASE 0x40014000 /* 0x40014000-0x400143ff: TIM9 timer */
+#define STM32_TIM10_BASE 0x40014400 /* 0x40014400-0x400147ff: TIM10 timer */
+#define STM32_TIM11_BASE 0x40014800 /* 0x40014800-0x40014bff: TIM11 timer */
+
+/* AHB1 Base Addresses **************************************************************/
+
+#define STM32_GPIOA_BASE 0x40020000 /* 0x40020000-0x400203ff: GPIO Port A */
+#define STM32_GPIOB_BASE 0x40020400 /* 0x40020400-0x400207ff: GPIO Port B */
+#define STM32_GPIOC_BASE 0x40020800 /* 0x40020800-0x40020bff: GPIO Port C */
+#define STM32_GPIOD_BASE 0X40020C00 /* 0x40020c00-0x40020fff: GPIO Port D */
+#define STM32_GPIOE_BASE 0x40021000 /* 0x40021000-0x400213ff: GPIO Port E */
+#define STM32_GPIOF_BASE 0x40021400 /* 0x40021400-0x400217ff: GPIO Port F */
+#define STM32_GPIOG_BASE 0x40021800 /* 0x40021800-0x40021bff: GPIO Port G */
+#define STM32_GPIOH_BASE 0x40021C00 /* 0x40021C00-0x40021fff: GPIO Port H */
+#define STM32_GPIOI_BASE 0x40022000 /* 0x40022000-0x400223ff: GPIO Port I */
+#define STM32_CRC_BASE 0x40023000 /* 0x40023000-0x400233ff: CRC */
+#define STM32_RCC_BASE 0x40023800 /* 0x40023800-0x40023bff: Reset and Clock control RCC */
+#define STM32_FLASHIF_BASE 0x40023c00 /* 0x40023c00-0x40023fff: Flash memory interface */
+#define STM32_BKPSRAM_BASE 0x40024000 /* 0x40024000-0x40024fff: Backup SRAM (BKPSRAM) */
+#define STM32_DMA1_BASE 0x40026000 /* 0x40026000-0x400263ff: DMA1 */
+#define STM32_DMA2_BASE 0x40026400 /* 0x40026400-0x400267ff: DMA2 */
+#define STM32_ETHERNET_BASE 0x40028000 /* 0x40028000-0x400283ff: Ethernet MAC */
+ /* 0x40028400-0x400287ff: Ethernet MAC */
+ /* 0x40028800-0x40028bff: Ethernet MAC */
+ /* 0x40028c00-0x40028fff: Ethernet MAC */
+ /* 0x40029000-0x400293ff: Ethernet MAC */
+#define STM32_OTGHS_BASE 0x40040000 /* 0x40040000-0x4007ffff: USB OTG HS */
+#define STM32_PERIPHBB_BASE 0x42000000 /* Peripheral bit-band region */
+
+/* AHB2 Base Addresses **************************************************************/
+
+#define STM32_OTGFS_BASE 0x50000000 /* 0x50000000-0x5003ffff: USB OTG FS */
+#define STM32_DCMI_BASE 0x50050000 /* 0x50050000-0x500503ff: DCMI */
+#define STM32_CRYP_BASE 0x50060000 /* 0x50060000-0x500603ff: CRYP */
+#define STM32_HASH_BASE 0x50060400 /* 0x50060400-0x500607ff: HASH */
+#define STM32_RNG_BASE 0x50060800 /* 0x50060800-0x50060bff: RNG */
+
+/* Cortex-M4 Base Addresses *********************************************************/
+/* Other registers -- see armv7-m/nvic.h for standard Cortex-M3 registers in this
+ * address range
+ */
+
+#define STM32_SCS_BASE 0xe000e000
+#define STM32_DEBUGMCU_BASE 0xe0042000
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_MEMORYMAP_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_pinmap.h
new file mode 100644
index 000000000..2c8587855
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_pinmap.h
@@ -0,0 +1,695 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f20xxx_pinmap.h
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_CHIP_STM32F20XXX_PINMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_PINMAP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "stm32_gpio.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Alternate Pin Functions. All members of the STM32F20xxx family share the same
+ * pin multiplexing (although they may differ in the pins physically available).
+ *
+ * Alternative pin selections are provided with a numeric suffix like _1, _2, etc.
+ * Drivers, however, will use the pin selection without the numeric suffix.
+ * Additional definitions are required in the board.h file. For example, if
+ * CAN1_RX connects vis PA11 on some board, then the following definitions should
+ * appear inthe board.h header file for that board:
+ *
+ * #define GPIO_CAN1_RX GPIO_CAN1_RX_1
+ *
+ * The driver will then automatically configre PA11 as the CAN1 RX pin.
+ */
+
+/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
+ * Additional effort is required to select specific GPIO options such as frequency,
+ * open-drain/push-pull, and pull-up/down! Just the basics are defined for most
+ * pins in this file.
+ */
+
+/* ADC */
+
+#define GPIO_ADC1_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC1_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC1_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC1_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC1_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_ADC1_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_ADC1_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_ADC1_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ADC1_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ADC1_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_ADC1_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC1_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC1_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC1_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC1_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ADC1_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5)
+
+#define GPIO_ADC2_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC2_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC2_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC2_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC2_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_ADC2_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_ADC2_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_ADC2_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ADC2_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ADC2_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_ADC2_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC2_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC2_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC2_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC2_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ADC2_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5)
+
+#define GPIO_ADC3_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC3_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC3_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC3_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC3_IN4 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN6)
+#define GPIO_ADC3_IN5 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN7)
+#define GPIO_ADC3_IN6 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN8)
+#define GPIO_ADC3_IN7 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN9)
+#define GPIO_ADC3_IN9 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN3)
+#define GPIO_ADC3_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC3_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC3_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC3_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC3_IN14 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN4)
+#define GPIO_ADC3_IN15 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN5)
+
+/* CAN */
+
+#define GPIO_CAN1_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_CAN1_RX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_CAN1_RX_3 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_CAN1_RX_4 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN9)
+#define GPIO_CAN1_TX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_CAN1_TX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_CAN1_TX_3 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_CAN1_TX_4 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN13)
+
+#define GPIO_CAN2_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_CAN2_RX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_CAN2_TX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_CAN2_TX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6)
+
+/* DAC -" Once the DAC channelx is enabled, the corresponding GPIO pin
+ * (PA4 or PA5) is automatically connected to the analog converter output
+ * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin
+ * should first be configured to analog (AIN)".
+ */
+
+#define GPIO_DAC1_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_DAC2_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5)
+
+/* Digital Camera Interface (DCMI) */
+
+#define GPIO_DCMI_D0_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_DCMI_D0_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_DCMI_D0_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN9)
+#define GPIO_DCMI_D1_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_DCMI_D1_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_DCMI_D1_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN10)
+#define GPIO_DCMI_D2_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_DCMI_D2_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN0)
+#define GPIO_DCMI_D2_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN11)
+#define GPIO_DCMI_D3_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_DCMI_D3_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN1)
+#define GPIO_DCMI_D3_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN12)
+#define GPIO_DCMI_D4_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_DCMI_D4_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_DCMI_D4_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN14)
+#define GPIO_DCMI_D5_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_DCMI_D5_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN4)
+#define GPIO_DCMI_D6_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_DCMI_D6_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_DCMI_D6_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN6)
+#define GPIO_DCMI_D7_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_DCMI_D7_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_DCMI_D7_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN7)
+#define GPIO_DCMI_D8_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN10)
+#define GPIO_DCMI_D8_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN1)
+#define GPIO_DCMI_D9_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_DCMI_D9_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN2)
+#define GPIO_DCMI_D10_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_DCMI_D10_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN3)
+#define GPIO_DCMI_D11_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTD|GPIO_PIN2)
+#define GPIO_DCMI_D11_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN15)
+#define GPIO_DCMI_D12 (GPIO_ALT|GPIO_AF13|GPIO_PORTF|GPIO_PIN11)
+#define GPIO_DCMI_D13_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTG|GPIO_PIN15)
+#define GPIO_DCMI_D13_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN0)
+#define GPIO_DCMI_HSYNC_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_DCMI_HSYNC_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN8)
+#define GPIO_DCMI_PIXCK (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_DCMI_VSYNC_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_DCMI_VSYNC_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN5)
+
+/* Clocks outputs */
+
+#define GPIO_MCO1 (GPIO_ALT|GPIO_AF0|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_MCO2 (GPIO_ALT|GPIO_AF0|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
+
+/* Ethernet MAC */
+
+#define GPIO_ETH_MDC (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ETH_MDIO (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ETH_MII_COL_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ETH_MII_COL_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN3)
+#define GPIO_ETH_MII_CRS_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ETH_MII_CRS_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN2)
+#define GPIO_ETH_MII_RXD0 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ETH_MII_RXD1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN5)
+#define GPIO_ETH_MII_RXD2_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ETH_MII_RXD2_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6)
+#define GPIO_ETH_MII_RXD3_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_ETH_MII_RXD3_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN7)
+#define GPIO_ETH_MII_RX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ETH_MII_RX_DV (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ETH_MII_RX_ER_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_ETH_MII_RX_ER_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN10)
+#define GPIO_ETH_MII_TXD0_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_ETH_MII_TXD0_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_ETH_MII_TXD1_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_ETH_MII_TXD1_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14)
+#define GPIO_ETH_MII_TXD2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ETH_MII_TXD3_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_ETH_MII_TXD3_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_ETH_MII_TX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ETH_MII_TX_EN_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_ETH_MII_TX_EN_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11)
+#define GPIO_ETH_PPS_OUT_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_ETH_PPS_OUT_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN8)
+#define GPIO_ETH_RMII_CRS_DV (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULLGPIO_PORTA|GPIO_PIN7)
+#define GPIO_ETH_RMII_REF_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ETH_RMII_RXD0 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ETH_RMII_RXD1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN5)
+#define GPIO_ETH_RMII_TXD0_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_ETH_RMII_TXD0_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_ETH_RMII_TXD1_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_ETH_RMII_TXD1_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14)
+#define GPIO_ETH_RMII_TX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ETH_RMII_TX_EN_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_ETH_RMII_TX_EN_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11)
+
+/* Flexible Static Memory Controller (FSMC) */
+
+#define GPIO_FSMC_A0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN0)
+#define GPIO_FSMC_A1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN1)
+#define GPIO_FSMC_A2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN2)
+#define GPIO_FSMC_A3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN3)
+#define GPIO_FSMC_A4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN4)
+#define GPIO_FSMC_A5 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN5)
+#define GPIO_FSMC_A6 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN12)
+#define GPIO_FSMC_A7 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN13)
+#define GPIO_FSMC_A8 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN14)
+#define GPIO_FSMC_A9 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN15)
+#define GPIO_FSMC_A10 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN0)
+#define GPIO_FSMC_A11 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN1)
+#define GPIO_FSMC_A12 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN2)
+#define GPIO_FSMC_A13 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN3)
+#define GPIO_FSMC_A14 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN4)
+#define GPIO_FSMC_A15 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN5)
+#define GPIO_FSMC_A16 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN11)
+#define GPIO_FSMC_A17 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_FSMC_A18 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN13)
+#define GPIO_FSMC_A19 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_FSMC_A20 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_FSMC_A21 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_FSMC_A22 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_FSMC_A23 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_FSMC_A24 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_FSMC_A25 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN14)
+#define GPIO_FSMC_NBL1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN1)
+#define GPIO_FSMC_CD (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN9)
+#define GPIO_FSMC_CLK (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN3)
+#define GPIO_FSMC_D0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_FSMC_D1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_FSMC_D2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_FSMC_D3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_FSMC_D4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN7)
+#define GPIO_FSMC_D5 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_FSMC_D6 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_FSMC_D7 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_FSMC_D8 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_FSMC_D9 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_FSMC_D10 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_FSMC_D11 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_FSMC_D12 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_FSMC_D13 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN8)
+#define GPIO_FSMC_D14 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_FSMC_D15 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN10)
+#define GPIO_FSMC_INT2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN6)
+#define GPIO_FSMC_INT3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN7)
+#define GPIO_FSMC_INTR (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN10)
+#define GPIO_FSMC_NBL0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN0)
+#define GPIO_FSMC_NCE2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN7)
+#define GPIO_FSMC_NCE3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN9)
+#define GPIO_FSMC_NCE4_1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN10)
+#define GPIO_FSMC_NCE4_2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN11)
+#define GPIO_FSMC_NE1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN7)
+#define GPIO_FSMC_NE2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN9)
+#define GPIO_FSMC_NE3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN10)
+#define GPIO_FSMC_NE4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN12)
+#define GPIO_FSMC_NIORD (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN6)
+#define GPIO_FSMC_NIOWR (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN8)
+#define GPIO_FSMC_NL (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_FSMC_NOE (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_FSMC_NREG (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN7)
+#define GPIO_FSMC_NWAIT (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_FSMC_NWE (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN5)
+
+/* I2C */
+
+#define GPIO_I2C1_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_I2C1_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_I2C1_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_I2C1_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5)
+
+#define GPIO_I2C2_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2C2_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTF|GPIO_PIN1)
+#define GPIO_I2C2_SCL_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN4)
+#define GPIO_I2C2_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_I2C2_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTF|GPIO_PIN0)
+#define GPIO_I2C2_SDA_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN5)
+#define GPIO_I2C2_SMBA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_I2C2_SMBA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN2)
+#define GPIO_I2C2_SMBA_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6)
+
+#define GPIO_I2C3_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_I2C3_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN7)
+#define GPIO_I2C3_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_I2C3_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN8)
+#define GPIO_I2C3_SMBA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_I2C3_SMBA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9)
+
+/* I2S */
+
+#define GPIO_I2S2_CK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2S2_CK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_I2S2_CK_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN1)
+#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_I2S2_SD_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_I2S2_SD_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_I2S2_SD_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN3)
+#define GPIO_I2S2_WS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_I2S2_WS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_I2S2_WS_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_I2S2_WS_4 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN0)
+
+#define GPIO_I2S2EXT_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_I2S2EXT_SD_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_I2S2EXT_SD_3 (GPIO_ALT|GPIO_AF6|GPIO_PORTI|GPIO_PIN2)
+
+#define GPIO_I2S3_CK_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_I2S3_CK_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN10)
+#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_I2S3_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_I2S3_SD_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_I2S3_WS_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_I2S3_WS_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN15)
+
+#define GPIO_I2S3EXT_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_I2S3EXT_SD_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN4)
+
+#define GPIO_I2S_CKIN (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN9)
+
+/* JTAG */
+
+#define GPIO_JTCK_SWCLK (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN14)
+#define GPIO_JTDI (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_JTDO (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_JTMS_SWDIO (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN13)
+#define GPIO_JTRST (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN4)
+
+/* OTG FS/HS */
+
+#define GPIO_OTGFS_DM (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_OTGFS_DP (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_OTGFS_ID (GPIO_ALT|GPIO_PULLUP|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_OTGFS_SCL (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_OTGFS_SDA (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_OTGFS_SOF (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8)
+
+#define GPIO_OTGHS_DM (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_OTGHS_DP (GPIO_ALT|GPIO_AF12|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_OTGHS_ID (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_OTGHS_INTN_1 (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_OTGFS_INTN_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_OTGHS_SCL (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_OTGHS_SDA (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_OTGHS_SOF (GPIO_ALT|GPIO_AF12|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_OTGHS_ULPI_CK (GPIO_ALT|GPIO_AF10|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_OTGHS_ULPI_D0 (GPIO_ALT|GPIO_AF10|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_OTGHS_ULPI_D1 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_OTGHS_ULPI_D2 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_OTGHS_ULPI_D3 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_OTGHS_ULPI_D4 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_OTGHS_ULPI_D5 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_OTGHS_ULPI_D6 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_OTGHS_ULPI_D7 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_OTGHS_ULPI_DIR_1 (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_OTGHS_ULPI_DIR_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTI|GPIO_PIN11)
+#define GPIO_OTGHS_ULPI_NXT_1 (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_OTGHS_ULPI_NXT_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTH|GPIO_PIN4)
+#define GPIO_OTGHS_ULPI_STP (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN0)
+
+/* RTC */
+
+#define GPIO_RTC_50HZ (GPIO_ALT|GPIO_AF0|GPIO_PORTC|GPIO_PIN15)
+
+/* SDIO */
+
+#define GPIO_SDIO_CK (GPIO_ALT|GPIO_AF12|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN2)
+#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_SDIO_D1 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_SDIO_D2 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10)
+#define GPIO_SDIO_D3 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_SDIO_D4 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_SDIO_D5 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_SDIO_D6 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_SDIO_D7 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
+
+/* SPI */
+
+#define GPIO_SPI1_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_SPI1_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN4)
+#define GPIO_SPI1_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_SPI1_MOSI_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_SPI1_NSS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_SPI1_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_SPI1_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_SPI1_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN3)
+
+#define GPIO_SPI2_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_SPI2_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_SPI2_MISO_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN2)
+#define GPIO_SPI2_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_SPI2_MOSI_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_SPI2_MOSI_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN3)
+#define GPIO_SPI2_NSS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_SPI2_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_SPI2_NSS_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN0)
+#define GPIO_SPI2_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_SPI2_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_SPI2_SCK_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN1)
+
+#define GPIO_SPI3_MISO_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN4)
+#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_SPI3_MOSI_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_SPI3_MOSI_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_SPI3_NSS_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_SPI3_NSS_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_SPI3_SCK_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_SPI3_SCK_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN10)
+
+/* Timers */
+
+#define GPIO_TIM1_BKIN_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM1_BKIN_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_TIM1_BKIN_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_TIM1_CH1N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM1_CH1N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_TIM1_CH1N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_TIM1_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_TIM1_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_TIM1_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_TIM1_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_TIM1_CH2N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM1_CH2N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_TIM1_CH2N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_TIM1_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_TIM1_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_TIM1_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_TIM1_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_TIM1_CH3N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_TIM1_CH3N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_TIM1_CH3N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_TIM1_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_TIM1_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_TIM1_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_TIM1_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_TIM1_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_TIM1_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_TIM1_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_TIM1_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_TIM1_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_TIM1_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN7)
+
+#define GPIO_TIM2_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM2_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_TIM2_CH1IN_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_TIM2_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM2_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_TIM2_CH1OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_TIM2_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM2_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_TIM2_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM2_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_TIM2_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM2_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_TIM2_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM2_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_TIM2_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM2_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_TIM2_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM2_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_TIM2_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM2_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_TIM2_ETR_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5)
+
+#define GPIO_TIM3_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM3_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN4)
+#define GPIO_TIM3_CH1IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM3_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM3_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN4)
+#define GPIO_TIM3_CH1OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM3_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM3_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_TIM3_CH2IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM3_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM3_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_TIM3_CH2OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM3_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM3_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM3_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM3_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM3_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_TIM3_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM3_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_TIM3_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM3_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN2)
+
+#define GPIO_TIM4_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_TIM4_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_TIM4_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_TIM4_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_TIM4_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_TIM4_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN13)
+#define GPIO_TIM4_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_TIM4_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN13)
+#define GPIO_TIM4_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_TIM4_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_TIM4_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_TIM4_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_TIM4_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_TIM4_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_TIM4_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_TIM4_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_TIM4_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN0)
+
+#define GPIO_TIM5_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10)
+#define GPIO_TIM5_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN10)
+#define GPIO_TIM5_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN11)
+#define GPIO_TIM5_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN11)
+#define GPIO_TIM5_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN12)
+#define GPIO_TIM5_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN12)
+#define GPIO_TIM5_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM5_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN0)
+#define GPIO_TIM5_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM5_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN0)
+#define GPIO_TIM5_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10)
+
+#define GPIO_TIM8_BKIN_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM8_BKIN_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTI|GPIO_PIN4)
+#define GPIO_TIM8_CH1N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_TIM8_CH1N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM8_CH1N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN13)
+#define GPIO_TIM8_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM8_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN5)
+#define GPIO_TIM8_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM8_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN5)
+#define GPIO_TIM8_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM8_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN6)
+#define GPIO_TIM8_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM8_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN6)
+#define GPIO_TIM8_CH2N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM8_CH2N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_TIM8_CH2N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN14)
+#define GPIO_TIM8_CH3N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_TIM8_CH3N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_TIM8_CH3N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN15)
+#define GPIO_TIM8_CH3IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM8_CH3IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN7)
+#define GPIO_TIM8_CH3OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM8_CH3OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN7)
+#define GPIO_TIM8_CH4IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM8_CH4IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN2)
+#define GPIO_TIM8_CH4OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM8_CH4OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN2)
+#define GPIO_TIM8_ETR_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM8_ETR_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN3)
+
+#define GPIO_TIM9_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM9_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_TIM9_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM9_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_TIM9_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM9_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_TIM9_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM9_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN6)
+
+#define GPIO_TIM10_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_TIM10_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN6)
+#define GPIO_TIM10_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_TIM10_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN6)
+
+#define GPIO_TIM11_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_TIM11_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN7)
+#define GPIO_TIM11_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_TIM11_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN7)
+
+#define GPIO_TIM12_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN6)
+#define GPIO_TIM12_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_TIM12_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6)
+#define GPIO_TIM12_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_TIM12_CH2IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_TIM12_CH2IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN9)
+#define GPIO_TIM12_CH2OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_TIM12_CH2OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9)
+
+#define GPIO_TIM13_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM13_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN8)
+#define GPIO_TIM13_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM13_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN8)
+
+#define GPIO_TIM14_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM14_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN9)
+#define GPIO_TIM14_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM14_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN9)
+
+/* Trace */
+
+#define GPIO_TRACECLK (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_TRACED0 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_TRACED1 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_TRACED2 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_TRACED3 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_TRACESWO (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN3)
+
+/* UARTs/USARTs */
+
+#define GPIO_USART1_CK (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_USART1_CTS (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_USART1_RTS (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_USART1_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_USART1_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_USART1_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_USART1_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6)
+
+#define GPIO_USART2_CK_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_USART2_CK_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN7)
+#define GPIO_USART2_CTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_USART2_CTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN3)
+#define GPIO_USART2_RTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_USART2_RTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_USART2_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_USART2_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_USART2_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_USART2_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN5)
+
+#define GPIO_USART3_CK_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_USART3_CK_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_USART3_CK_3 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN10)
+#define GPIO_USART3_CTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_USART3_CTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN11)
+#define GPIO_USART3_RTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_USART3_RTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_USART3_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_USART3_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_USART3_RX_3 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_USART3_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_USART3_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10)
+#define GPIO_USART3_TX_3 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN8)
+
+#define GPIO_UART4_RX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_UART4_RX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_UART4_TX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_UART4_TX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10)
+
+#define GPIO_UART5_RX (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN2)
+#define GPIO_UART5_TX (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN12)
+
+#define GPIO_USART6_CK_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_USART6_CK_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN7)
+#define GPIO_USART6_CTS_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_USART6_CTS_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN15)
+#define GPIO_USART6_RTS_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN12)
+#define GPIO_USART6_RTS_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN8)
+#define GPIO_USART6_RX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_USART6_RX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN9)
+#define GPIO_USART6_TX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_USART6_TX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_PINMAP_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h
new file mode 100644
index 000000000..8a926250b
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rcc.h
@@ -0,0 +1,504 @@
+/****************************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f20xxx_rcc.h
+ *
+ * Copyright (C) 2012 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_STM32_CHIP_STM32F20XXX_RCC_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RCC_H
+
+/****************************************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************************************/
+
+/* Register Offsets *********************************************************************************/
+
+#define STM32_RCC_CR_OFFSET 0x0000 /* Clock control register */
+#define STM32_RCC_PLLCFG_OFFSET 0x0004 /* PLL configuration register */
+#define STM32_RCC_CFGR_OFFSET 0x0008 /* Clock configuration register */
+#define STM32_RCC_CIR_OFFSET 0x000c /* Clock interrupt register */
+#define STM32_RCC_AHB1RSTR_OFFSET 0x0010 /* AHB1 peripheral reset register */
+#define STM32_RCC_AHB2RSTR_OFFSET 0x0014 /* AHB2 peripheral reset register */
+#define STM32_RCC_AHB3RSTR_OFFSET 0x0018 /* AHB3 peripheral reset register */
+#define STM32_RCC_APB1RSTR_OFFSET 0x0020 /* APB1 Peripheral reset register */
+#define STM32_RCC_APB2RSTR_OFFSET 0x0024 /* APB2 Peripheral reset register */
+#define STM32_RCC_AHB1ENR_OFFSET 0x0030 /* AHB1 Peripheral Clock enable register */
+#define STM32_RCC_AHB2ENR_OFFSET 0x0034 /* AHB2 Peripheral Clock enable register */
+#define STM32_RCC_AHB3ENR_OFFSET 0x0038 /* AHB3 Peripheral Clock enable register */
+#define STM32_RCC_APB1ENR_OFFSET 0x0040 /* APB1 Peripheral Clock enable register */
+#define STM32_RCC_APB2ENR_OFFSET 0x0044 /* APB2 Peripheral Clock enable register */
+#define STM32_RCC_AHB1LPENR_OFFSET 0x0050 /* RCC AHB1 low power modeperipheral clock enable register */
+#define STM32_RCC_AH2BLPENR_OFFSET 0x0054 /* RCC AHB2 low power modeperipheral clock enable register */
+#define STM32_RCC_AH3BLPENR_OFFSET 0x0058 /* RCC AHB3 low power modeperipheral clock enable register */
+#define STM32_RCC_APB1LPENR_OFFSET 0x0060 /* RCC APB1 low power modeperipheral clock enable register */
+#define STM32_RCC_APB2LPENR_OFFSET 0x0060 /* RCC APB2 low power modeperipheral clock enable register */
+#define STM32_RCC_BDCR_OFFSET 0x0070 /* Backup domain control register */
+#define STM32_RCC_CSR_OFFSET 0x0074 /* Control/status register */
+#define STM32_RCC_SSCGR_OFFSET 0x0080 /* Spread spectrum clock generation register */
+#define STM32_RCC_PLLI2SCFGR_OFFSET 0x0084 /* PLLI2S configuration register */
+
+/* Register Addresses *******************************************************************************/
+
+#define STM32_RCC_CR (STM32_RCC_BASE+STM32_RCC_CR_OFFSET)
+#define STM32_RCC_PLLCFG (STM32_RCC_BASE+STM32_RCC_PLLCFG_OFFSET)
+#define STM32_RCC_CFGR (STM32_RCC_BASE+STM32_RCC_CFGR_OFFSET)
+#define STM32_RCC_CIR (STM32_RCC_BASE+STM32_RCC_CIR_OFFSET)
+#define STM32_RCC_AHB1RSTR (STM32_RCC_BASE+STM32_RCC_AHB1RSTR_OFFSET)
+#define STM32_RCC_AHB2RSTR (STM32_RCC_BASE+STM32_RCC_AHB2RSTR_OFFSET)
+#define STM32_RCC_AHB3RSTR (STM32_RCC_BASE+STM32_RCC_AHB3RSTR_OFFSET)
+#define STM32_RCC_APB1RSTR (STM32_RCC_BASE+STM32_RCC_APB1RSTR_OFFSET)
+#define STM32_RCC_APB2RSTR (STM32_RCC_BASE+STM32_RCC_APB2RSTR_OFFSET)
+#define STM32_RCC_AHB1ENR (STM32_RCC_BASE+STM32_RCC_AHB1ENR_OFFSET)
+#define STM32_RCC_AHB2ENR (STM32_RCC_BASE+STM32_RCC_AHB2ENR_OFFSET)
+#define STM32_RCC_AHB3ENR (STM32_RCC_BASE+STM32_RCC_AHB3ENR_OFFSET)
+#define STM32_RCC_APB1ENR (STM32_RCC_BASE+STM32_RCC_APB1ENR_OFFSET)
+#define STM32_RCC_APB2ENR (STM32_RCC_BASE+STM32_RCC_APB2ENR_OFFSET)
+#define STM32_RCC_AHB1LPENR (STM32_RCC_BASE+STM32_RCC_AHB1LPENR_OFFSET)
+#define STM32_RCC_AH2BLPENR (STM32_RCC_BASE+STM32_RCC_AH2BLPENR)
+#define STM32_RCC_AH3BLPENR (STM32_RCC_BASE+STM32_RCC_AH3BLPENR_OFFSET)
+#define STM32_RCC_APB1LPENR (STM32_RCC_BASE+STM32_RCC_APB1LPENR_OFFSET)
+#define STM32_RCC_APB2LPENR (STM32_RCC_BASE+STM32_RCC_APB2LPENR_OFFSET)
+#define STM32_RCC_BDCR (STM32_RCC_BASE+STM32_RCC_BDCR_OFFSET)
+#define STM32_RCC_CSR (STM32_RCC_BASE+STM32_RCC_CSR_OFFSET)
+#define STM32_RCC_SSCGR (STM32_RCC_BASE+STM32_RCC_SSCGR_OFFSET)
+#define STM32_RCC_PLLI2SCFGR (STM32_RCC_BASE+STM32_RCC_PLLI2SCFGR_OFFSET)
+
+/* Register Bitfield Definitions ********************************************************************/
+
+/* Clock control register */
+
+#define RCC_CR_HSION (1 << 0) /* Bit 0: Internal High Speed clock enable */
+#define RCC_CR_HSIRDY (1 << 1) /* Bit 1: Internal High Speed clock ready flag */
+#define RCC_CR_HSITRIM_SHIFT (3) /* Bits 7-3: Internal High Speed clock trimming */
+#define RCC_CR_HSITRIM_MASK (0x1f << RCC_CR_HSITRIM_SHIFT)
+#define RCC_CR_HSICAL_SHIFT (8) /* Bits 15-8: Internal High Speed clock Calibration */
+#define RCC_CR_HSICAL_MASK (0xff << RCC_CR_HSICAL_SHIFT)
+#define RCC_CR_HSEON (1 << 16) /* Bit 16: External High Speed clock enable */
+#define RCC_CR_HSERDY (1 << 17) /* Bit 17: External High Speed clock ready flag */
+#define RCC_CR_HSEBYP (1 << 18) /* Bit 18: External High Speed clock Bypass */
+#define RCC_CR_CSSON (1 << 19) /* Bit 19: Clock Security System enable */
+#define RCC_CR_PLLON (1 << 24) /* Bit 24: PLL enable */
+#define RCC_CR_PLLRDY (1 << 25) /* Bit 25: PLL clock ready flag */
+#define RCC_CR_PLLI2SON (1 << 26) /* Bit 26: PLLI2S enable */
+#define RCC_CR_PLLI2SRDY (1 << 27) /* Bit 27: PLLI2S clock ready flag */
+
+/* PLL configuration register */
+
+#define RCC_PLLCFG_PLLM_SHIFT (0) /* Bits 0-5: Main PLL (PLL) and audio PLL (PLLI2S)
+ * input clock divider */
+#define RCC_PLLCFG_PLLM_MASK (0x3f << RCC_PLLCFG_PLLM_SHIFT)
+# define RCC_PLLCFG_PLLM(n) ((n) << RCC_PLLCFG_PLLM_SHIFT) /* n = 2..63 */
+#define RCC_PLLCFG_PLLN_SHIFT (6) /* Bits 6-14: Main PLL (PLL) VCO multiplier */
+#define RCC_PLLCFG_PLLN_MASK (0x1ff << RCC_PLLCFG_PLLN_SHIFT)
+# define RCC_PLLCFG_PLLN(n) ((n) << RCC_PLLCFG_PLLN_SHIFT) /* n = 2..432 */
+#define RCC_PLLCFG_PLLP_SHIFT (16) /* Bits 16-17: Main PLL (PLL) main system clock divider */
+#define RCC_PLLCFG_PLLP_MASK (3 << RCC_PLLCFG_PLLP_SHIFT)
+# define RCC_PLLCFG_PLLP(n) ((((n)>>1)-1)<< RCC_PLLCFG_PLLP_SHIFT) /* n=2,4,6,8 */
+# define RCC_PLLCFG_PLLP_2 (0 << RCC_PLLCFG_PLLP_SHIFT) /* 00: PLLP = 2 */
+# define RCC_PLLCFG_PLLP_4 (1 << RCC_PLLCFG_PLLP_SHIFT) /* 01: PLLP = 4 */
+# define RCC_PLLCFG_PLLP_6 (2 << RCC_PLLCFG_PLLP_SHIFT) /* 10: PLLP = 6 */
+# define RCC_PLLCFG_PLLP_8 (3 << RCC_PLLCFG_PLLP_SHIFT) /* 11: PLLP = 8 */
+#define RCC_PLLCFG_PLLSRC (1 << 22) /* Bit 22: Main PLL(PLL) and audio PLL (PLLI2S)
+ * entry clock source */
+# define RCC_PLLCFG_PLLSRC_HSI (0)
+# define RCC_PLLCFG_PLLSRC_HSE RCC_PLLCFG_PLLSRC
+#define RCC_PLLCFG_PLLQ_SHIFT (24) /* Bits 24-27: Main PLL (PLL) divider
+ * (USB OTG FS, SDIO and RNG clocks) */
+#define RCC_PLLCFG_PLLQ_MASK (15 << RCC_PLLCFG_PLLQ_SHIFT)
+# define RCC_PLLCFG_PLLQ(n) ((n) << RCC_PLLCFG_PLLQ_SHIFT) /* n=2..15 */
+
+#define RCC_PLLCFG_RESET (0x24003010) /* PLLCFG reset value */
+
+/* Clock configuration register */
+
+#define RCC_CFGR_SW_SHIFT (0) /* Bits 0-1: System clock Switch */
+#define RCC_CFGR_SW_MASK (3 << RCC_CFGR_SW_SHIFT)
+# define RCC_CFGR_SW_HSI (0 << RCC_CFGR_SW_SHIFT) /* 00: HSI selected as system clock */
+# define RCC_CFGR_SW_HSE (1 << RCC_CFGR_SW_SHIFT) /* 01: HSE selected as system clock */
+# define RCC_CFGR_SW_PLL (2 << RCC_CFGR_SW_SHIFT) /* 10: PLL selected as system clock */
+#define RCC_CFGR_SWS_SHIFT (2) /* Bits 2-3: System Clock Switch Status */
+#define RCC_CFGR_SWS_MASK (3 << RCC_CFGR_SWS_SHIFT)
+# define RCC_CFGR_SWS_HSI (0 << RCC_CFGR_SWS_SHIFT) /* 00: HSI oscillator used as system clock */
+# define RCC_CFGR_SWS_HSE (1 << RCC_CFGR_SWS_SHIFT) /* 01: HSE oscillator used as system clock */
+# define RCC_CFGR_SWS_PLL (2 << RCC_CFGR_SWS_SHIFT) /* 10: PLL used as system clock */
+#define RCC_CFGR_HPRE_SHIFT (4) /* Bits 4-7: AHB prescaler */
+#define RCC_CFGR_HPRE_MASK (0x0f << RCC_CFGR_HPRE_SHIFT)
+# define RCC_CFGR_HPRE_SYSCLK (0 << RCC_CFGR_HPRE_SHIFT) /* 0xxx: SYSCLK not divided */
+# define RCC_CFGR_HPRE_SYSCLKd2 (8 << RCC_CFGR_HPRE_SHIFT) /* 1000: SYSCLK divided by 2 */
+# define RCC_CFGR_HPRE_SYSCLKd4 (9 << RCC_CFGR_HPRE_SHIFT) /* 1001: SYSCLK divided by 4 */
+# define RCC_CFGR_HPRE_SYSCLKd8 (10 << RCC_CFGR_HPRE_SHIFT) /* 1010: SYSCLK divided by 8 */
+# define RCC_CFGR_HPRE_SYSCLKd16 (11 << RCC_CFGR_HPRE_SHIFT) /* 1011: SYSCLK divided by 16 */
+# define RCC_CFGR_HPRE_SYSCLKd64 (12 << RCC_CFGR_HPRE_SHIFT) /* 1100: SYSCLK divided by 64 */
+# define RCC_CFGR_HPRE_SYSCLKd128 (13 << RCC_CFGR_HPRE_SHIFT) /* 1101: SYSCLK divided by 128 */
+# define RCC_CFGR_HPRE_SYSCLKd256 (14 << RCC_CFGR_HPRE_SHIFT) /* 1110: SYSCLK divided by 256 */
+# define RCC_CFGR_HPRE_SYSCLKd512 (15 << RCC_CFGR_HPRE_SHIFT) /* 1111: SYSCLK divided by 512 */
+#define RCC_CFGR_PPRE1_SHIFT (10) /* Bits 10-12: APB Low speed prescaler (APB1) */
+#define RCC_CFGR_PPRE1_MASK (7 << RCC_CFGR_PPRE1_SHIFT)
+# define RCC_CFGR_PPRE1_HCLK (0 << RCC_CFGR_PPRE1_SHIFT) /* 0xx: HCLK not divided */
+# define RCC_CFGR_PPRE1_HCLKd2 (4 << RCC_CFGR_PPRE1_SHIFT) /* 100: HCLK divided by 2 */
+# define RCC_CFGR_PPRE1_HCLKd4 (5 << RCC_CFGR_PPRE1_SHIFT) /* 101: HCLK divided by 4 */
+# define RCC_CFGR_PPRE1_HCLKd8 (6 << RCC_CFGR_PPRE1_SHIFT) /* 110: HCLK divided by 8 */
+# define RCC_CFGR_PPRE1_HCLKd16 (7 << RCC_CFGR_PPRE1_SHIFT) /* 111: HCLK divided by 16 */
+#define RCC_CFGR_PPRE2_SHIFT (13) /* Bits 13-15: APB High speed prescaler (APB2) */
+#define RCC_CFGR_PPRE2_MASK (7 << RCC_CFGR_PPRE2_SHIFT)
+# define RCC_CFGR_PPRE2_HCLK (0 << RCC_CFGR_PPRE2_SHIFT) /* 0xx: HCLK not divided */
+# define RCC_CFGR_PPRE2_HCLKd2 (4 << RCC_CFGR_PPRE2_SHIFT) /* 100: HCLK divided by 2 */
+# define RCC_CFGR_PPRE2_HCLKd4 (5 << RCC_CFGR_PPRE2_SHIFT) /* 101: HCLK divided by 4 */
+# define RCC_CFGR_PPRE2_HCLKd8 (6 << RCC_CFGR_PPRE2_SHIFT) /* 110: HCLK divided by 8 */
+# define RCC_CFGR_PPRE2_HCLKd16 (7 << RCC_CFGR_PPRE2_SHIFT) /* 111: HCLK divided by 16 */
+#define RCC_CFGR_RTCPRE_SHIFT (16) /* Bits 16-20: APB High speed prescaler (APB2) */
+#define RCC_CFGR_RTCPRE_MASK (31 << RCC_CFGR_RTCPRE)
+# define RCC_CFGR_RTCPRE(n) ((n) << RCC_CFGR_RTCPRE) /* HSE/n, n=1..31 */
+#define RCC_CFGR_MCO1_SHIFT (21) /* Bits 21-22: Microcontroller Clock Output */
+#define RCC_CFGR_MCO1_MASK (3 << RCC_CFGR_MCO1_SHIFT)
+# define RCC_CFGR_MCO1_HSI (0 << RCC_CFGR_MCO1_SHIFT) /* 00: HSI clock selected */
+# define RCC_CFGR_MCO1_LSE (1 << RCC_CFGR_MCO1_SHIFT) /* 01: LSE oscillator selected */
+# define RCC_CFGR_MCO1_HSE (2 << RCC_CFGR_MCO1_SHIFT) /* 10: HSE oscillator clock selected */
+# define RCC_CFGR_MCO1_PLL (3 << RCC_CFGR_MCO1_SHIFT) /* 11: PLL clock selected */
+#define TCC_CFGR_I2SSRC (1 << 23) /* Bit 23: I2S clock selection */
+#define RCC_CFGR_MCO1PRE_SHIFT (24) /* Bits 24-26: MCO1 prescaler */
+#define RCC_CFGR_MCO1PRE_MASK (7 << RCC_CFGR_MCO1PRE_SHIFT)
+# define RCC_CFGR_MCO1PRE_NONE (0 << RCC_CFGR_MCO1PRE_SHIFT) /* 0xx: no division */
+# define RCC_CFGR_MCO1PRE_DIV2 (4 << RCC_CFGR_MCO1PRE_SHIFT) /* 100: division by 2 */
+# define RCC_CFGR_MCO1PRE_DIV3 (5 << RCC_CFGR_MCO1PRE_SHIFT) /* 101: division by 3 */
+# define RCC_CFGR_MCO1PRE_DIV4 (6 << RCC_CFGR_MCO1PRE_SHIFT) /* 110: division by 4 */
+# define RCC_CFGR_MCO1PRE_DIV5 (7 << RCC_CFGR_MCO1PRE_SHIFT) /* 111: division by 5 */
+#define RCC_CFGR_MCO2PRE_SHIFT (27) /* Bits 27-29: MCO2 prescaler */
+#define RCC_CFGR_MCO2PRE_MASK (7 << RCC_CFGR_MCO2PRE_SHIFT)
+# define RCC_CFGR_MCO2PRE_NONE (0 << RCC_CFGR_MCO2PRE_SHIFT) /* 0xx: no division */
+# define RCC_CFGR_MCO2PRE_DIV2 (4 << RCC_CFGR_MCO2PRE_SHIFT) /* 100: division by 2 */
+# define RCC_CFGR_MCO2PRE_DIV3 (5 << RCC_CFGR_MCO2PRE_SHIFT) /* 101: division by 3 */
+# define RCC_CFGR_MCO2PRE_DIV4 (6 << RCC_CFGR_MCO2PRE_SHIFT) /* 110: division by 4 */
+# define RCC_CFGR_MCO2PRE_DIV5 (7 << RCC_CFGR_MCO2PRE_SHIFT) /* 111: division by 5 */
+#define RCC_CFGR_MCO2_SHIFT (30) /* Bits 30-31: Microcontroller clock output 2 */
+#define RCC_CFGR_MCO2_MASK (3 << RCC_CFGR_MCO2_SHIFT)
+# define RCC_CFGR_MCO2_SYSCLK (0 << RCC_CFGR_MCO2_SHIFT) /* 00: System clock (SYSCLK) selected */
+# define RCC_CFGR_MCO2_PLLI2S (1 << RCC_CFGR_MCO2_SHIFT) /* 01: PLLI2S clock selected */
+# define RCC_CFGR_MCO2_HSE (2 << RCC_CFGR_MCO2_SHIFT) /* 10: HSE oscillator clock selected */
+# define RCC_CFGR_MCO2_PLL (3 << RCC_CFGR_MCO2_SHIFT) /* 11: PLL clock selected */
+
+/* Clock interrupt register */
+
+#define RCC_CIR_LSIRDYF (1 << 0) /* Bit 0: LSI Ready Interrupt flag */
+#define RCC_CIR_LSERDYF (1 << 1) /* Bit 1: LSE Ready Interrupt flag */
+#define RCC_CIR_HSIRDYF (1 << 2) /* Bit 2: HSI Ready Interrupt flag */
+#define RCC_CIR_HSERDYF (1 << 3) /* Bit 3: HSE Ready Interrupt flag */
+#define RCC_CIR_PLLRDYF (1 << 4) /* Bit 4: PLL Ready Interrupt flag */
+#define RCC_CIR_PLLI2SRDYF (1 << 5) /* Bit 5: PLLI2S Ready Interrupt flag */
+#define RCC_CIR_CSSF (1 << 7) /* Bit 7: Clock Security System Interrupt flag */
+#define RCC_CIR_LSIRDYIE (1 << 8) /* Bit 8: LSI Ready Interrupt Enable */
+#define RCC_CIR_LSERDYIE (1 << 9) /* Bit 9: LSE Ready Interrupt Enable */
+#define RCC_CIR_HSIRDYIE (1 << 10) /* Bit 10: HSI Ready Interrupt Enable */
+#define RCC_CIR_HSERDYIE (1 << 11) /* Bit 11: HSE Ready Interrupt Enable */
+#define RCC_CIR_PLLRDYIE (1 << 12) /* Bit 12: PLL Ready Interrupt Enable */
+#define RCC_CIR_PLLI2SRDYIE (1 << 13) /* Bit 13: PLLI2S Ready Interrupt enable */
+#define RCC_CIR_LSIRDYC (1 << 16) /* Bit 16: LSI Ready Interrupt Clear */
+#define RCC_CIR_LSERDYC (1 << 17) /* Bit 17: LSE Ready Interrupt Clear */
+#define RCC_CIR_HSIRDYC (1 << 18) /* Bit 18: HSI Ready Interrupt Clear */
+#define RCC_CIR_HSERDYC (1 << 19) /* Bit 19: HSE Ready Interrupt Clear */
+#define RCC_CIR_PLLRDYC (1 << 20) /* Bit 20: PLL Ready Interrupt Clear */
+#define RCC_CIR_PLLI2SRDYC (1 << 21) /* Bit 21: PLLI2S Ready Interrupt clear */
+#define RCC_CIR_CSSC (1 << 23) /* Bit 23: Clock Security System Interrupt Clear */
+
+/* AHB1 peripheral reset register */
+
+#define RCC_AHB1RSTR_GPIOARST (1 << 0) /* Bit 0: IO port A reset */
+#define RCC_AHB1RSTR_GPIOBRST (1 << 1) /* Bit 1: IO port B reset */
+#define RCC_AHB1RSTR_GPIOCRST (1 << 2) /* Bit 2: IO port C reset */
+#define RCC_AHB1RSTR_GPIODRST (1 << 3) /* Bit 3: IO port D reset */
+#define RCC_AHB1RSTR_GPIOERST (1 << 4) /* Bit 4: IO port E reset */
+#define RCC_AHB1RSTR_GPIOFRST (1 << 5) /* Bit 5: IO port F reset */
+#define RCC_AHB1RSTR_GPIOGRST (1 << 6) /* Bit 6: IO port G reset */
+#define RCC_AHB1RSTR_GPIOHRST (1 << 7) /* Bit 7: IO port H reset */
+#define RCC_AHB1RSTR_CRCRST (1 << 12) /* Bit 12 IO port I reset */
+#define RCC_AHB1RSTR_DMA1RST (1 << 21) /* Bit 21: DMA1 reset */
+#define RCC_AHB1RSTR_DMA2RST (1 << 22) /* Bit 22: DMA2 reset */
+#define RCC_AHB1RSTR_ETHMACRST (1 << 25) /* Bit 25: Ethernet MAC reset */
+#define RCC_AHB1RSTR_OTGHSRST (1 << 29) /* Bit 29: USB OTG HS module reset */
+
+/* AHB2 peripheral reset register */
+
+#define RCC_AHB2RSTR_DCMIRST (1 << 0) /* Bit 0: Camera interface reset */
+#define RCC_AHB2RSTR_CRYPRST (1 << 4) /* Bit 4: Cryptographic module reset */
+#define RCC_AHB2RSTR_HASHRST (1 << 5) /* Bit 5: Hash module reset */
+#define RCC_AHB2RSTR_RNGRST (1 << 6) /* Bit 6: Random number generator module reset */
+#define RCC_AHB2RSTR_OTGFSRST (1 << 7) /* Bit 7: USB OTG FS module reset */
+
+/* AHB3 peripheral reset register */
+
+#define RCC_AHB3RSTR_FSMCRST (1 << 0) /* Bit 0: Flexible static memory controller module reset */
+
+/* APB1 Peripheral reset register */
+
+#define RCC_APB1RSTR_TIM2RST (1 << 0) /* Bit 0: TIM2 reset */
+#define RCC_APB1RSTR_TIM3RST (1 << 1) /* Bit 1: TIM3 reset */
+#define RCC_APB1RSTR_TIM4RST (1 << 2) /* Bit 2: TIM4 reset */
+#define RCC_APB1RSTR_TIM5RST (1 << 3) /* Bit 3: TIM5 reset */
+#define RCC_APB1RSTR_TIM6RST (1 << 4) /* Bit 4: TIM6 reset */
+#define RCC_APB1RSTR_TIM7RST (1 << 5) /* Bit 5: TIM7 reset */
+#define RCC_APB1RSTR_TIM12RST (1 << 6) /* Bit 6: TIM12 reset */
+#define RCC_APB1RSTR_TIM13RST (1 << 7) /* Bit 7: TIM13 reset */
+#define RCC_APB1RSTR_TIM14RST (1 << 8) /* Bit 8: TIM14 reset */
+#define RCC_APB1RSTR_WWDGRST (1 << 11) /* Bit 11: Window watchdog reset */
+#define RCC_APB1RSTR_SPI2RST (1 << 14) /* Bit 14: SPI 2 reset */
+#define RCC_APB1RSTR_SPI3RST (1 << 15) /* Bit 15: SPI 3 reset */
+#define RCC_APB1RSTR_USART2RST (1 << 17) /* Bit 17: USART 2 reset */
+#define RCC_APB1RSTR_USART3RST (1 << 18) /* Bit 18: USART 3 reset */
+#define RCC_APB1RSTR_UART4RST (1 << 19) /* Bit 19: USART 4 reset */
+#define RCC_APB1RSTR_UART5RST (1 << 20) /* Bit 20: USART 5 reset */
+#define RCC_APB1RSTR_I2C1RST (1 << 21) /* Bit 21: I2C 1 reset */
+#define RCC_APB1RSTR_I2C2RST (1 << 22) /* Bit 22: I2C 2 reset */
+#define RCC_APB1RSTR_I2C3RST (1 << 23) /* Bit 23: I2C3 reset */
+#define RCC_APB1RSTR_CAN1RST (1 << 25) /* Bit 25: CAN1 reset */
+#define RCC_APB1RSTR_CAN2RST (1 << 26) /* Bit 26: CAN2 reset */
+#define RCC_APB1RSTR_PWRRST (1 << 28) /* Bit 28: Power interface reset */
+#define RCC_APB1RSTR_DACRST (1 << 29) /* Bit 29: DAC reset */
+
+/* APB2 Peripheral reset register */
+
+#define RCC_APB2RSTR_TIM1RST (1 << 0) /* Bit 0: TIM1 reset */
+#define RCC_APB2RSTR_TIM8RST (1 << 1) /* Bit 1: TIM8 reset */
+#define RCC_APB2RSTR_USART1RST (1 << 4) /* Bit 4: USART1 reset */
+#define RCC_APB2RSTR_USART6RST (1 << 5) /* Bit 5: USART6 reset */
+#define RCC_APB2RSTR_ADCRST (1 << 8) /* Bit 8: ADC interface reset (common to all ADCs) */
+#define RCC_APB2RSTR_SDIORST (1 << 11) /* Bit 11: SDIO reset */
+#define RCC_APB2RSTR_SPI1RST (1 << 12) /* Bit 12: SPI 1 reset */
+#define RCC_APB2RSTR_SYSCFGRST (1 << 14) /* Bit 14: System configuration controller reset */
+#define RCC_APB2RSTR_TIM9RST (1 << 16) /* Bit 16: TIM9 reset */
+#define RCC_APB2RSTR_TIM10RST (1 << 17) /* Bit 17: TIM10 reset */
+#define RCC_APB2RSTR_TIM11RST (1 << 18) /* Bit 18: TIM11 reset */
+
+/* AHB1 Peripheral Clock enable register */
+
+#define RCC_AHB1ENR_GPIOEN(n) (1 << (n))
+#define RCC_AHB1ENR_GPIOAEN (1 << 0) /* Bit 0: IO port A clock enable */
+#define RCC_AHB1ENR_GPIOBEN (1 << 1) /* Bit 1: IO port B clock enable */
+#define RCC_AHB1ENR_GPIOCEN (1 << 2) /* Bit 2: IO port C clock enable */
+#define RCC_AHB1ENR_GPIODEN (1 << 3) /* Bit 3: IO port D clock enable */
+#define RCC_AHB1ENR_GPIOEEN (1 << 4) /* Bit 4: IO port E clock enable */
+#define RCC_AHB1ENR_GPIOFEN (1 << 5) /* Bit 5: IO port F clock enable */
+#define RCC_AHB1ENR_GPIOGEN (1 << 6) /* Bit 6: IO port G clock enable */
+#define RCC_AHB1ENR_GPIOHEN (1 << 7) /* Bit 7: IO port H clock enable */
+#define RCC_AHB1ENR_GPIOIEN (1 << 8) /* Bit 8: IO port I clock enable */
+#define RCC_AHB1ENR_CRCEN (1 << 12) /* Bit 12: CRC clock enable */
+#define RCC_AHB1ENR_BKPSRAMEN (1 << 18) /* Bit 18: Backup SRAM interface clock enable */
+#define RCC_AHB1ENR_DMA1EN (1 << 21) /* Bit 21: DMA1 clock enable */
+#define RCC_AHB1ENR_DMA2EN (1 << 22) /* Bit 22: DMA2 clock enable */
+#define RCC_AHB1ENR_ETHMACEN (1 << 25) /* Bit 25: Ethernet MAC clock enable */
+#define RCC_AHB1ENR_ETHMACTXEN (1 << 26) /* Bit 26: Ethernet Transmission clock enable */
+#define RCC_AHB1ENR_ETHMACRXEN (1 << 27) /* Bit 27: Ethernet Reception clock enable */
+#define RCC_AHB1ENR_ETHMACPTPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable */
+#define RCC_AHB1ENR_OTGHSEN (1 << 29) /* Bit 29: USB OTG HS clock enable */
+#define RCC_AHB1ENR_OTGHSULPIEN (1 << 30) /* Bit 30: USB OTG HSULPI clock enable */
+
+/* AHB2 Peripheral Clock enable register */
+
+#define RCC_AHB2ENR_DCMIEN (1 << 0) /* Bit 0: Camera interface enable */
+#define RCC_AHB2ENR_CRYPEN (1 << 4) /* Bit 4: Cryptographic modules clock enable */
+#define RCC_AHB2ENR_HASHEN (1 << 5) /* Bit 5: Hash modules clock enable */
+#define RCC_AHB2ENR_RNGEN (1 << 6) /* Bit 6: Random number generator clock enable */
+#define RCC_AHB2ENR_OTGFSEN (1 << 7) /* Bit 7: USB OTG FS clock enable */
+
+/* AHB3 Peripheral Clock enable register */
+
+#define RCC_AHB3ENR_FSMCEN (1 << 0) /* Bit 0: Flexible static memory controller module clock enable */
+
+/* APB1 Peripheral Clock enable register */
+
+#define RCC_APB1ENR_TIM2EN (1 << 0) /* Bit 0: TIM2 clock enable */
+#define RCC_APB1ENR_TIM3EN (1 << 1) /* Bit 1: TIM3 clock enable */
+#define RCC_APB1ENR_TIM4EN (1 << 2) /* Bit 2: TIM4 clock enable */
+#define RCC_APB1ENR_TIM5EN (1 << 3) /* Bit 3: TIM5 clock enable */
+#define RCC_APB1ENR_TIM6EN (1 << 4) /* Bit 4: TIM6 clock enable */
+#define RCC_APB1ENR_TIM7EN (1 << 5) /* Bit 5: TIM7 clock enable */
+#define RCC_APB1ENR_TIM12EN (1 << 6) /* Bit 6: TIM12 clock enable */
+#define RCC_APB1ENR_TIM13EN (1 << 7) /* Bit 7: TIM13 clock enable */
+#define RCC_APB1ENR_TIM14EN (1 << 8) /* Bit 8: TIM14 clock enable */
+#define RCC_APB1ENR_WWDGEN (1 << 11) /* Bit 11: Window watchdog clock enable */
+#define RCC_APB1ENR_SPI2EN (1 << 14) /* Bit 14: SPI2 clock enable */
+#define RCC_APB1ENR_SPI3EN (1 << 15) /* Bit 15: SPI3 clock enable */
+#define RCC_APB1ENR_USART2EN (1 << 17) /* Bit 17: USART 2 clock enable */
+#define RCC_APB1ENR_USART3EN (1 << 18) /* Bit 18: USART3 clock enable */
+#define RCC_APB1ENR_UART4EN (1 << 19) /* Bit 19: UART4 clock enable */
+#define RCC_APB1ENR_UART5EN (1 << 20) /* Bit 20: UART5 clock enable */
+#define RCC_APB1ENR_I2C1EN (1 << 21) /* Bit 21: I2C1 clock enable */
+#define RCC_APB1ENR_I2C2EN (1 << 22) /* Bit 22: I2C2 clock enable */
+#define RCC_APB1ENR_I2C3EN (1 << 23) /* Bit 23: I2C3 clock enable */
+#define RCC_APB1ENR_CAN1EN (1 << 25) /* Bit 25: CAN 1 clock enable */
+#define RCC_APB1ENR_CAN2EN (1 << 26) /* Bit 26: CAN 2 clock enable */
+#define RCC_APB1ENR_PWREN (1 << 28) /* Bit 28: Power interface clock enable */
+#define RCC_APB1ENR_DACEN (1 << 29) /* Bit 29: DAC interface clock enable */
+
+/* APB2 Peripheral Clock enable register */
+
+#define RCC_APB2ENR_TIM1EN (1 << 0) /* Bit 0: TIM1 clock enable */
+#define RCC_APB2ENR_TIM8EN (1 << 1) /* Bit 1: TIM8 clock enable */
+#define RCC_APB2ENR_USART1EN (1 << 4) /* Bit 4: USART1 clock enable */
+#define RCC_APB2ENR_USART6EN (1 << 5) /* Bit 5: USART6 clock enable */
+#define RCC_APB2ENR_ADC1EN (1 << 8) /* Bit 8: ADC1 clock enable */
+#define RCC_APB2ENR_ADC2EN (1 << 9) /* Bit 9: ADC2 clock enable */
+#define RCC_APB2ENR_ADC3EN (1 << 10) /* Bit 10: ADC3 clock enable */
+#define RCC_APB2ENR_SDIOEN (1 << 11) /* Bit 11: SDIO clock enable */
+#define RCC_APB2ENR_SPI1EN (1 << 12) /* Bit 12: SPI1 clock enable */
+#define RCC_APB2ENR_SYSCFGEN (1 << 14) /* Bit 14: System configuration controller clock enable */
+#define RCC_APB2ENR_TIM9EN (1 << 16) /* Bit 16: TIM9 clock enable */
+#define RCC_APB2ENR_TIM10EN (1 << 17) /* Bit 17: TIM10 clock enable */
+#define RCC_APB2ENR_TIM11EN (1 << 18) /* Bit 18: TIM11 clock enable */
+
+/* RCC AHB1 low power modeperipheral clock enable register */
+
+#define RCC_AHB1LPENR_GPIOLPEN(n) (1 << (n))
+#define RCC_AHB1LPENR_GPIOALPEN (1 << 0) /* Bit 0: IO port A clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOBLPEN (1 << 1) /* Bit 1: IO port B clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOCLPEN (1 << 2) /* Bit 2: IO port C clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIODLPEN (1 << 3) /* Bit 3: IO port D clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOELPEN (1 << 4) /* Bit 4: IO port E clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOFLPEN (1 << 5) /* Bit 5: IO port F clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOGLPEN (1 << 6) /* Bit 6: IO port G clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOHLPEN (1 << 7) /* Bit 7: IO port H clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOILPEN (1 << 8) /* Bit 8: IO port I clock enable during Sleep mode */
+#define RCC_AHB1LPENR_CRCLPEN (1 << 12) /* Bit 12: CRC clock enable during Sleep mode */
+#define RCC_AHB1LPENR_FLITFLPEN (1 << 15) /* Bit 15: Flash interface clock enable during Sleep mode */
+#define RCC_AHB1LPENR_SRAM1LPEN (1 << 16) /* Bit 16: SRAM 1 interface clock enable during Sleep mode */
+#define RCC_AHB1LPENR_SRAM2LPEN (1 << 17) /* Bit 17: SRAM 2 interface clock enable during Sleep mode */
+#define RCC_AHB1LPENR_BKPSRAMLPEN (1 << 18) /* Bit 18: Backup SRAM interface clock enable during Sleep mode */
+#define RCC_AHB1LPENR_DMA1LPEN (1 << 21) /* Bit 21: DMA1 clock enable during Sleep mode */
+#define RCC_AHB1LPENR_DMA2LPEN (1 << 22) /* Bit 22: DMA2 clock enable during Sleep mode */
+#define RCC_AHB1LPENR_ETHMACLPEN (1 << 25) /* Bit 25: Ethernet MAC clock enable during Sleep mode */
+#define RCC_AHB1LPENR_ETHMACTXLPEN (1 << 26) /* Bit 26: Ethernet Transmission clock enable during Sleep mode */
+#define RCC_AHB1LPENR_ETHMACRXLPEN (1 << 27) /* Bit 27: Ethernet Reception clock enable during Sleep mode */
+#define RCC_AHB1LPENR_ETHMACPTPLPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable during Sleep mode */
+#define RCC_AHB1LPENR_OTGHSLPEN (1 << 29) /* Bit 29: USB OTG HS clock enable during Sleep mode */
+#define RCC_AHB1LPENR_OTGHSULPILPEN (1 << 30) /* Bit 30: USB OTG HSULPI clock enable during Sleep mode */
+
+/* RCC AHB2 low power modeperipheral clock enable register */
+
+#define RCC_AHB2LPENR_DCMILPEN (1 << 0) /* Bit 0: Camera interface enable during Sleep mode */
+#define RCC_AHB2LPENR_CRYPLPEN (1 << 4) /* Bit 4: Cryptographic modules clock enable during Sleep mode */
+#define RCC_AHB2LPENR_HASHLPEN (1 << 5) /* Bit 5: Hash modules clock enable during Sleep mode */
+#define RCC_AHB2LPENR_RNGLPEN (1 << 6) /* Bit 6: Random number generator clock enable during Sleep mode */
+#define RCC_AHB2LPENR_OTGFLPSEN (1 << 7) /* Bit 7: USB OTG FS clock enable during Sleep mode */
+
+/* RCC AHB3 low power modeperipheral clock enable register */
+
+#define RCC_AHB3LPENR_FSMLPEN (1 << 0) /* Bit 0: Flexible static memory controller module clock
+ * enable during Sleep mode */
+
+/* RCC APB1 low power modeperipheral clock enable register */
+
+#define RCC_APB1LPENR_TIM2LPEN (1 << 0) /* Bit 0: TIM2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM3LPEN (1 << 1) /* Bit 1: TIM3 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM4LPEN (1 << 2) /* Bit 2: TIM4 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM5LPEN (1 << 3) /* Bit 3: TIM5 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM6LPEN (1 << 4) /* Bit 4: TIM6 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM7LPEN (1 << 5) /* Bit 5: TIM7 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM12LPEN (1 << 6) /* Bit 6: TIM12 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM13LPEN (1 << 7) /* Bit 7: TIM13 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM14LPEN (1 << 8) /* Bit 8: TIM14 clock enable during Sleep mode */
+#define RCC_APB1LPENR_WWDGLPEN (1 << 11) /* Bit 11: Window watchdog clock enable during Sleep mode */
+#define RCC_APB1LPENR_SPI2LPEN (1 << 14) /* Bit 14: SPI2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_SPI3LPEN (1 << 15) /* Bit 15: SPI3 clock enable during Sleep mode */
+#define RCC_APB1LPENR_USART2LPEN (1 << 17) /* Bit 17: USART 2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_USART3LPEN (1 << 18) /* Bit 18: USART3 clock enable during Sleep mode */
+#define RCC_APB1LPENR_UART4LPEN (1 << 19) /* Bit 19: UART4 clock enable during Sleep mode */
+#define RCC_APB1LPENR_UART5LPEN (1 << 20) /* Bit 20: UART5 clock enable during Sleep mode */
+#define RCC_APB1LPENR_I2C1LPEN (1 << 21) /* Bit 21: I2C1 clock enable during Sleep mode */
+#define RCC_APB1LPENR_I2C2LPEN (1 << 22) /* Bit 22: I2C2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_I2C3LPEN (1 << 23) /* Bit 23: I2C3 clock enable during Sleep mode */
+#define RCC_APB1LPENR_CAN1LPEN (1 << 25) /* Bit 25: CAN 1 clock enable during Sleep mode */
+#define RCC_APB1LPENR_CAN2LPEN (1 << 26) /* Bit 26: CAN 2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_PWRLPEN (1 << 28) /* Bit 28: Power interface clock enable during Sleep mode */
+#define RCC_APB1LPENR_DACLPEN (1 << 29) /* Bit 29: DAC interface clock enable during Sleep mode */
+
+/* RCC APB2 low power modeperipheral clock enable register */
+
+#define RCC_APB2LPENR_TIM1LPEN (1 << 0) /* Bit 0: TIM1 clock enable during Sleep mode */
+#define RCC_APB2LPENR_TIM8LPEN (1 << 1) /* Bit 1: TIM8 clock enable during Sleep mode */
+#define RCC_APB2LPENR_USART1LPEN (1 << 4) /* Bit 4: USART1 clock enable during Sleep mode */
+#define RCC_APB2LPENR_USART6LPEN (1 << 5) /* Bit 5: USART6 clock enable during Sleep mode */
+#define RCC_APB2LPENR_ADC1LPEN (1 << 8) /* Bit 8: ADC1 clock enable during Sleep mode */
+#define RCC_APB2LPENR_ADC2LPEN (1 << 9) /* Bit 9: ADC2 clock enable during Sleep mode */
+#define RCC_APB2LPENR_ADC3LPEN (1 << 10) /* Bit 10: ADC3 clock enable during Sleep mode */
+#define RCC_APB2LPENR_SDIOLPEN (1 << 11) /* Bit 11: SDIO clock enable during Sleep mode */
+#define RCC_APB2LPENR_SPI1LPEN (1 << 12) /* Bit 12: SPI1 clock enable during Sleep mode */
+#define RCC_APB2LPENR_SYSCFGLPEN (1 << 14) /* Bit 14: System configuration controller clock enable during Sleep mode */
+#define RCC_APB2LPENR_TIM9LPEN (1 << 16) /* Bit 16: TIM9 clock enable during Sleep mode */
+#define RCC_APB2LPENR_TIM10LPEN (1 << 17) /* Bit 17: TIM10 clock enable during Sleep mode */
+#define RCC_APB2LPENR_TIM11LPEN (1 << 18) /* Bit 18: TIM11 clock enable during Sleep mode */
+
+/* Backup domain control register */
+
+#define RCC_BDCR_LSEON (1 << 0) /* Bit 0: External Low Speed oscillator enable */
+#define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */
+#define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */
+#define RCC_BDCR_RTCSEL_SHIFT (8) /* Bits 9:8: RTC clock source selection */
+#define RCC_BDCR_RTCSEL_MASK (3 << RCC_BDCR_RTCSEL_SHIFT)
+# define RCC_BDCR_RTCSEL_NOCLK (0 << RCC_BDCR_RTCSEL_SHIFT) /* 00: No clock */
+# define RCC_BDCR_RTCSEL_LSE (1 << RCC_BDCR_RTCSEL_SHIFT) /* 01: LSE oscillator clock used as RTC clock */
+# define RCC_BDCR_RTCSEL_LSI (2 << RCC_BDCR_RTCSEL_SHIFT) /* 10: LSI oscillator clock used as RTC clock */
+# define RCC_BDCR_RTCSEL_HSE (3 << RCC_BDCR_RTCSEL_SHIFT) /* 11: HSE oscillator clock divided by 128 used as RTC clock */
+#define RCC_BDCR_RTCEN (1 << 15) /* Bit 15: RTC clock enable */
+#define RCC_BDCR_BDRST (1 << 16) /* Bit 16: Backup domain software reset */
+
+/* Control/status register */
+
+#define RCC_CSR_LSION (1 << 0) /* Bit 0: Internal Low Speed oscillator enable */
+#define RCC_CSR_LSIRDY (1 << 1) /* Bit 1: Internal Low Speed oscillator Ready */
+#define RCC_CSR_RMVF (1 << 24) /* Bit 24: Remove reset flag */
+#define RCC_CSR_BORRSTF (1 << 25) /* Bit 25: BOR reset flag */
+#define RCC_CSR_PINRSTF (1 << 26) /* Bit 26: PIN reset flag */
+#define RCC_CSR_PORRSTF (1 << 27) /* Bit 27: POR/PDR reset flag */
+#define RCC_CSR_SFTRSTF (1 << 28) /* Bit 28: Software Reset flag */
+#define RCC_CSR_IWDGRSTF (1 << 29) /* Bit 29: Independent Watchdog reset flag */
+#define RCC_CSR_WWDGRSTF (1 << 30) /* Bit 30: Window watchdog reset flag */
+#define RCC_CSR_LPWRRSTF (1 << 31) /* Bit 31: Low-Power reset flag */
+
+/* Spread spectrum clock generation register */
+
+#define RCC_SSCGR_MODPER_SHIFT (0) /* Bit 0-12: Modulation period */
+#define RCC_SSCGR_MODPER_MASK (0x1fff << RCC_SSCGR_MODPER_SHIFT)
+# define RCC_SSCGR_MODPER(n) ((n) << RCC_SSCGR_MODPER_SHIFT)
+#define RCC_SSCGR_INCSTEP_SHIFT (13) /* Bit 13-27: Incrementation step */
+#define RCC_SSCGR_INCSTEP_MASK (0x7fff << RCC_SSCGR_INCSTEP_SHIFT)
+# define RCC_SSCGR_INCSTEP(n) ((n) << RCC_SSCGR_INCSTEP_SHIFT)
+#define RCC_SSCGR_SPREADSEL (1 << 30) /* Bit 30: Spread Select */
+#define RCC_SSCGR_SSCGEN (1 << 31) /* Bit 31: Spread spectrum modulation enable */
+
+/* PLLI2S configuration register */
+
+#define RCC_PLLI2SCFGR_PLLI2SN_SHIFT (6) /* Bits 6-14: PLLI2S multiplication factor for VCO */
+#define RCC_PLLI2SCFGR_PLLI2SN_MASK (0x1ff << RCC_PLLI2SCFGR_PLLI2SN_SHIFT)
+#define RCC_PLLI2SCFGR_PLLI2SR_SHIFT (28) /* Bits 28-30: PLLI2S division factor for I2S clocks */
+#define RCC_PLLI2SCFGR_PLLI2SR_MASK (7 << RCC_PLLI2SCFGR_PLLI2SR_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RCC_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rtc.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rtc.h
new file mode 100644
index 000000000..b0d7ec913
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_rtc.h
@@ -0,0 +1,338 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f20xxx_rtc.h
+ *
+ * Copyright (C) 2012 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_STM32_CHIP_STM32F20XXX_RTC_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RTC_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_RTC_TR_OFFSET 0x0000 /* RTC time register */
+#define STM32_RTC_DR_OFFSET 0x0004 /* RTC date register */
+#define STM32_RTC_CR_OFFSET 0x0008 /* RTC control register */
+#define STM32_RTC_ISR_OFFSET 0x000c /* RTC initialization and status register */
+#define STM32_RTC_PRER_OFFSET 0x0010 /* RTC prescaler register */
+#define STM32_RTC_WUTR_OFFSET 0x0014 /* RTC wakeup timer register */
+#define STM32_RTC_CALIBR_OFFSET 0x0018 /* RTC calibration register */
+#define STM32_RTC_ALRMAR_OFFSET 0x001c /* RTC alarm A register */
+#define STM32_RTC_ALRMBR_OFFSET 0x0020 /* RTC alarm B register */
+#define STM32_RTC_WPR_OFFSET 0x0024 /* RTC write protection register */
+#define STM32_RTC_SSR_OFFSET 0x0028 /* RTC sub second register */
+#define STM32_RTC_SHIFTR_OFFSET 0x002c /* RTC shift control register */
+#define STM32_RTC_TSTR_OFFSET 0x0030 /* RTC time stamp time register */
+#define STM32_RTC_TSDR_OFFSET 0x0030 /* RTC time stamp date register */
+#define STM32_RTC_TSSSR_OFFSET 0x0038 /* RTC timestamp sub second register */
+#define STM32_RTC_CALR_OFFSET 0x003c /* RTC calibration register */
+#define STM32_RTC_TAFCR_OFFSET 0x0040 /* RTC tamper and alternate function configuration register */
+#define STM32_RTC_ALRMASSR_OFFSET 0x0044 /* RTC alarm A sub second register */
+#define STM32_RTC_ALRMBSSR_OFFSET 0x0048 /* RTC alarm B sub second register */
+
+#define STM32_RTC_BKR_OFFSET(n) (0x0050+((n)<<2))
+#define STM32_RTC_BK0R_OFFSET 0x0050 /* RTC backup register 0 */
+#define STM32_RTC_BK1R_OFFSET 0x0054 /* RTC backup register 1 */
+#define STM32_RTC_BK2R_OFFSET 0x0058 /* RTC backup register 2 */
+#define STM32_RTC_BK3R_OFFSET 0x005c /* RTC backup register 3 */
+#define STM32_RTC_BK4R_OFFSET 0x0060 /* RTC backup register 4 */
+#define STM32_RTC_BK5R_OFFSET 0x0064 /* RTC backup register 5 */
+#define STM32_RTC_BK6R_OFFSET 0x0068 /* RTC backup register 6 */
+#define STM32_RTC_BK7R_OFFSET 0x006c /* RTC backup register 7 */
+#define STM32_RTC_BK8R_OFFSET 0x0070 /* RTC backup register 8 */
+#define STM32_RTC_BK9R_OFFSET 0x0074 /* RTC backup register 9 */
+#define STM32_RTC_BK10R_OFFSET 0x0078 /* RTC backup register 10 */
+#define STM32_RTC_BK11R_OFFSET 0x007c /* RTC backup register 11 */
+#define STM32_RTC_BK12R_OFFSET 0x0080 /* RTC backup register 12 */
+#define STM32_RTC_BK13R_OFFSET 0x0084 /* RTC backup register 13 */
+#define STM32_RTC_BK14R_OFFSET 0x0088 /* RTC backup register 14 */
+#define STM32_RTC_BK15R_OFFSET 0x008c /* RTC backup register 15 */
+#define STM32_RTC_BK16R_OFFSET 0x0090 /* RTC backup register 16 */
+#define STM32_RTC_BK17R_OFFSET 0x0094 /* RTC backup register 17 */
+#define STM32_RTC_BK18R_OFFSET 0x0098 /* RTC backup register 18 */
+#define STM32_RTC_BK19R_OFFSET 0x009c /* RTC backup register 19 */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_RTC_TR (STM32_RTC_BASE+STM32_RTC_TR_OFFSET)
+#define STM32_RTC_DR (STM32_RTC_BASE+STM32_RTC_DR_OFFSET)
+#define STM32_RTC_CR (STM32_RTC_BASE+STM32_RTC_CR_OFFSET)
+#define STM32_RTC_ISR (STM32_RTC_BASE+STM32_RTC_ISR_OFFSET)
+#define STM32_RTC_PRER (STM32_RTC_BASE+STM32_RTC_PRER_OFFSET)
+#define STM32_RTC_WUTR (STM32_RTC_BASE+STM32_RTC_WUTR_OFFSET)
+#define STM32_RTC_CALIBR (STM32_RTC_BASE+STM32_RTC_CALIBR_OFFSET)
+#define STM32_RTC_ALRMAR (STM32_RTC_BASE+STM32_RTC_ALRMAR_OFFSET)
+#define STM32_RTC_ALRMBR (STM32_RTC_BASE+STM32_RTC_ALRMBR_OFFSET)
+#define STM32_RTC_WPR (STM32_RTC_BASE+STM32_RTC_WPR_OFFSET)
+#define STM32_RTC_SSR (STM32_RTC_BASE+STM32_RTC_SSR_OFFSET)
+#define STM32_RTC_SHIFTR (STM32_RTC_BASE+STM32_RTC_SHIFTR_OFFSET)
+#define STM32_RTC_TSTR (STM32_RTC_BASE+STM32_RTC_TSTR_OFFSET)
+#define STM32_RTC_TSDR (STM32_RTC_BASE+STM32_RTC_TSDR_OFFSET)
+#define STM32_RTC_TSSSR (STM32_RTC_BASE+STM32_RTC_TSSSR_OFFSET)
+#define STM32_RTC_CALR (STM32_RTC_BASE+STM32_RTC_CALR_OFFSET)
+#define STM32_RTC_TAFCR (STM32_RTC_BASE+STM32_RTC_TAFCR_OFFSET)
+#define STM32_RTC_ALRMASSR (STM32_RTC_BASE+STM32_RTC_ALRMASSR_OFFSET)
+#define STM32_RTC_ALRMBSSR (STM32_RTC_BASE+STM32_RTC_ALRMBSSR_OFFSET)
+
+#define STM32_RTC_BKR(n) (STM32_RTC_BASE+STM32_RTC_BKR_OFFSET(n))
+#define STM32_RTC_BK0R (STM32_RTC_BASE+STM32_RTC_BK0R_OFFSET)
+#define STM32_RTC_BK1R (STM32_RTC_BASE+STM32_RTC_BK1R_OFFSET)
+#define STM32_RTC_BK2R (STM32_RTC_BASE+STM32_RTC_BK2R_OFFSET)
+#define STM32_RTC_BK3R (STM32_RTC_BASE+STM32_RTC_BK3R_OFFSET)
+#define STM32_RTC_BK4R (STM32_RTC_BASE+STM32_RTC_BK4R_OFFSET)
+#define STM32_RTC_BK5R (STM32_RTC_BASE+STM32_RTC_BK5R_OFFSET)
+#define STM32_RTC_BK6R (STM32_RTC_BASE+STM32_RTC_BK6R_OFFSET)
+#define STM32_RTC_BK7R (STM32_RTC_BASE+STM32_RTC_BK7R_OFFSET)
+#define STM32_RTC_BK8R (STM32_RTC_BASE+STM32_RTC_BK8R_OFFSET)
+#define STM32_RTC_BK9R (STM32_RTC_BASE+STM32_RTC_BK9R_OFFSET)
+#define STM32_RTC_BK10R (STM32_RTC_BASE+STM32_RTC_BK10R_OFFSET)
+#define STM32_RTC_BK11R (STM32_RTC_BASE+STM32_RTC_BK11R_OFFSET)
+#define STM32_RTC_BK12R (STM32_RTC_BASE+STM32_RTC_BK12R_OFFSET)
+#define STM32_RTC_BK13R (STM32_RTC_BASE+STM32_RTC_BK13R_OFFSET)
+#define STM32_RTC_BK14R (STM32_RTC_BASE+STM32_RTC_BK14R_OFFSET)
+#define STM32_RTC_BK15R (STM32_RTC_BASE+STM32_RTC_BK15R_OFFSET)
+#define STM32_RTC_BK16R (STM32_RTC_BASE+STM32_RTC_BK16R_OFFSET)
+#define STM32_RTC_BK17R (STM32_RTC_BASE+STM32_RTC_BK17R_OFFSET)
+#define STM32_RTC_BK18R (STM32_RTC_BASE+STM32_RTC_BK18R_OFFSET)
+#define STM32_RTC_BK19R (STM32_RTC_BASE+STM32_RTC_BK19R_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* RTC time register */
+
+#define RTC_TR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format */
+#define RTC_TR_SU_MASK (15 << RTC_TR_SU_SHIFT)
+#define RTC_TR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format */
+#define RTC_TR_ST_MASK (7 << RTC_TR_ST_SHIFT)
+#define RTC_TR_MNU_SHIFT (8) /* Bit 8-11: Minute units in BCD format */
+#define RTC_TR_MNU_MASK (15 << RTC_TR_MNU_SHIFT)
+#define RTC_TR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format */
+#define RTC_TR_MNT_MASK (7 << RTC_TR_MNT_SHIFT)
+#define RTC_TR_HU_SHIFT (16) /* Bit 16-19: Hour units in BCD format */
+#define RTC_TR_HU_MASK (15 << RTC_TR_HU_SHIFT)
+#define RTC_TR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format */
+#define RTC_TR_HT_MASK (3 << RTC_TR_HT_SHIFT)
+#define RTC_TR_PM (1 << 22) /* Bit 22: AM/PM notation */
+#define RTC_TR_RESERVED_BITS (0xff808080)
+
+/* RTC date register */
+
+#define RTC_DR_DU_SHIFT (0) /* Bits 0-3: Date units in BCD format */
+#define RTC_DR_DU_MASK (15 << RTC_DR_DU_SHIFT)
+#define RTC_DR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */
+#define RTC_DR_DT_MASK (3 << RTC_DR_DT_SHIFT)
+#define RTC_DR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */
+#define RTC_DR_MU_MASK (15 << RTC_DR_MU_SHIFT)
+#define RTC_DR_MT (1 << 12) /* Bit 12: Month tens in BCD format */
+#define RTC_DR_WDU_SHIFT (13) /* Bits 13-15: Week day units */
+#define RTC_DR_WDU_MASK (7 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_MONDAY (1 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_TUESDAY (2 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_WEDNESDAY (3 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_THURSDAY (4 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_FRIDAY (5 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_SATURDAY (6 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_SUNDAY (7 << RTC_DR_WDU_SHIFT)
+#define RTC_DR_YU_SHIFT (16) /* Bits 16-19: Year units in BCD format */
+#define RTC_DR_YU_MASK (15 << RTC_DR_YU_SHIFT)
+#define RTC_DR_YT_SHIFT (20) /* Bits 20-23: Year tens in BCD format */
+#define RTC_DR_YT_MASK (15 << RTC_DR_YT_SHIFT)
+#define RTC_DR_RESERVED_BITS (0xff0000c0)
+
+/* RTC control register */
+
+#define RTC_CR_WUCKSEL_SHIFT (0) /* Bits 0-2: Wakeup clock selection */
+#define RTC_CR_WUCKSEL_MASK (7 << RTC_CR_WUCKSEL_SHIFT)
+# define RTC_CR_WUCKSEL_RTCDIV16 (0 << RTC_CR_WUCKSEL_SHIFT) /* 000: RTC/16 clock is selected */
+# define RTC_CR_WUCKSEL_RTCDIV8 (1 << RTC_CR_WUCKSEL_SHIFT) /* 001: RTC/8 clock is selected */
+# define RTC_CR_WUCKSEL_RTCDIV4 (2 << RTC_CR_WUCKSEL_SHIFT) /* 010: RTC/4 clock is selected */
+# define RTC_CR_WUCKSEL_RTCDIV2 (3 << RTC_CR_WUCKSEL_SHIFT) /* 011: RTC/2 clock is selected */
+# define RTC_CR_WUCKSEL_CKSPRE (4 << RTC_CR_WUCKSEL_SHIFT) /* 10x: ck_spre clock is selected */
+# define RTC_CR_WUCKSEL_CKSPREADD (6 << RTC_CR_WUCKSEL_SHIFT) /* 11x: ck_spr clock and 216 added WUT counter */
+#define RTC_CR_TSEDGE (1 << 3) /* Bit 3: Timestamp event active edge */
+#define RTC_CR_REFCKON (1 << 4) /* Bit 4: Reference clock detection enable (50 or 60 Hz) */
+#define RTC_CR_BYPSHAD (1 << 5) /* Bit 5: Bypass the shadow registers */
+#define RTC_CR_FMT (1 << 6) /* Bit 6: Hour format */
+#define RTC_CR_DCE (1 << 7) /* Bit 7: Coarse digital calibration enable */
+#define RTC_CR_ALRAE (1 << 8) /* Bit 8: Alarm A enable */
+#define RTC_CR_ALRBE (1 << 9) /* Bit 9: Alarm B enable */
+#define RTC_CR_WUTE (1 << 10) /* Bit 10: Wakeup timer enable */
+#define RTC_CR_TSE (1 << 11) /* Bit 11: Time stamp enable */
+#define RTC_CR_ALRAIE (1 << 12) /* Bit 12: Alarm A interrupt enable */
+#define RTC_CR_ALRBIE (1 << 13) /* Bit 13: Alarm B interrupt enable */
+#define RTC_CR_WUTIE (1 << 14) /* Bit 14: Wakeup timer interrupt enable */
+#define RTC_CR_TSIE (1 << 15) /* Bit 15: Timestamp interrupt enable */
+#define RTC_CR_ADD1H (1 << 16) /* Bit 16: Add 1 hour (summer time change) */
+#define RTC_CR_SUB1H (1 << 17) /* Bit 17: Subtract 1 hour (winter time change) */
+#define RTC_CR_BKP (1 << 18) /* Bit 18: Backup */
+#define RTC_CR_COSEL (1 << 19) /* Bit 19 : Calibration output selection */
+#define RTC_CR_POL (1 << 20) /* Bit 20: Output polarity */
+#define RTC_CR_OSEL_SHIFT (21) /* Bits 21-22: Output selection */
+#define RTC_CR_OSEL_MASK (3 << RTC_CR_OSEL_SHIFT)
+# define RTC_CR_OSEL_DISABLED (0 << RTC_CR_OSEL_SHIFT) /* 00: Output disabled */
+# define RTC_CR_OSEL_ALRMA (1 << RTC_CR_OSEL_SHIFT) /* 01: Alarm A output enabled */
+# define RTC_CR_OSEL_ALRMB (2 << RTC_CR_OSEL_SHIFT) /* 10: Alarm B output enabled */
+# define RTC_CR_OSEL_WUT (3 << RTC_CR_OSEL_SHIFT) /* 11: Wakeup output enabled */
+#define RTC_CR_COE (1 << 23) /* Bit 23: Calibration output enable */
+
+/* RTC initialization and status register */
+
+#define RTC_ISR_ALRAWF (1 << 0) /* Bit 0: Alarm A write flag */
+#define RTC_ISR_ALRBWF (1 << 1) /* Bit 1: Alarm B write flag */
+#define RTC_ISR_WUTWF (1 << 2) /* Bit 2: Wakeup timer write flag */
+#define RTC_ISR_SHPF (1 << 3) /* Bit 3: Shift operation pending */
+#define RTC_ISR_INITS (1 << 4) /* Bit 4: Initialization status flag */
+#define RTC_ISR_RSF (1 << 5) /* Bit 5: Registers synchronization flag */
+#define RTC_ISR_INITF (1 << 6) /* Bit 6: Initialization flag */
+#define RTC_ISR_INIT (1 << 7) /* Bit 7: Initialization mode */
+#define RTC_ISR_ALRAF (1 << 8) /* Bit 8: Alarm A flag */
+#define RTC_ISR_ALRBF (1 << 9) /* Bit 9: Alarm B flag */
+#define RTC_ISR_WUTF (1 << 10) /* Bit 10: Wakeup timer flag */
+#define RTC_ISR_TSF (1 << 11) /* Bit 11: Timestamp flag */
+#define RTC_ISR_TSOVF (1 << 12) /* Bit 12: Timestamp overflow flag */
+#define RTC_ISR_TAMP1F (1 << 13) /* Bit 13: Tamper detection flag */
+#define RTC_ISR_TAMP2F (1 << 14) /* Bit 14: TAMPER2 detection flag */
+#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending Flag */
+#define RTC_ISR_ALLFLAGS (0x00017fff)
+
+/* RTC prescaler register */
+
+#define RTC_PRER_PREDIV_S_SHIFT (0) /* Bits 0-14: Synchronous prescaler factor */
+#define RTC_PRER_PREDIV_S_MASK (0x7fff << RTC_PRER_PREDIV_S_SHIFT)
+#define RTC_PRER_PREDIV_A_SHIFT (16) /* Bits 16-22: Asynchronous prescaler factor */
+#define RTC_PRER_PREDIV_A_MASK (0x7f << RTC_PRER_PREDIV_A_SHIFT)
+
+/* RTC wakeup timer register */
+
+#define RTC_WUTR_MASK (0xffff) /* Bits 15:0 Wakeup auto-reload value bits */
+
+/* RTC calibration register */
+
+#define RTC_CALIBR_DCS (1 << 7) /* Bit 7 Digital calibration sign */
+#define RTC_CALIBR_DC_SHIFT (0) /* Bits 4:0 0-4: Digital calibration */
+#define RTC_CALIBR_DC_MASK (31 << RTC_CALIBR_DC_SHIFT)
+# define RTC_CALIBR_DC(n) (((n) >> 2) << RTC_CALIBR_DC_SHIFT) /* n= 0, 4, 8, ... 126 */
+
+/* RTC alarm A/B registers */
+
+#define RTC_ALRMR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format. */
+#define RTC_ALRMR_SU_MASK (15 << RTC_ALRMR_SU_SHIFT)
+#define RTC_ALRMR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format. */
+#define RTC_ALRMR_ST_MASK (7 << RTC_ALRMR_ST_SHIFT)
+#define RTC_ALRMR_MSK1 (1 << 7) /* Bit 7 : Alarm A seconds mask */
+#define RTC_ALRMR_MNU_SHIFT (8) /* Bits 8-11: Minute units in BCD format. */
+#define RTC_ALRMR_MNU_MASK (15 << RTC_ALRMR_MNU_SHIFT)
+#define RTC_ALRMR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format. */
+#define RTC_ALRMR_MNT_MASK (7 << RTC_ALRMR_MNT_SHIFT)
+#define RTC_ALRMR_MSK2 (1 << 15) /* Bit 15 : Alarm A minutes mask */
+#define RTC_ALRMR_HU_SHIFT (16) /* Bits 16-19: Hour units in BCD format. */
+#define RTC_ALRMR_HU_MASK (15 << RTC_ALRMR_HU_SHIFT)
+#define RTC_ALRMR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format. */
+#define RTC_ALRMR_HT_MASK (3 << RTC_ALRMR_HT_SHIFT)
+#define RTC_ALRMR_PM (1 << 22) /* Bit 22 : AM/PM notation */
+#define RTC_ALRMR_MSK3 (1 << 23) /* Bit 23 : Alarm A hours mask */
+#define RTC_ALRMR_DU_SHIFT (24) /* Bits 24-27: Date units or day in BCD format. */
+#define RTC_ALRMR_DU_MASK (15 << RTC_ALRMR_DU_SHIFT)
+#define RTC_ALRMR_DT_SHIFT (28) /* Bits 28-29: Date tens in BCD format. */
+#define RTC_ALRMR_DT_MASK (3 << RTC_ALRMR_DT_SHIFT)
+#define RTC_ALRMR_WDSEL (1 << 30) /* Bit 30: Week day selection */
+#define RTC_ALRMR_MSK4 (1 << 31) /* Bit 31: Alarm A date mask */
+
+/* RTC write protection register */
+
+#define RTC_WPR_MASK (0xff) /* Bits 0-7: Write protection key */
+
+/* RTC sub second register */
+
+#define RTC_SSR_MASK (0xffff) /* Bits 0-15: Sub second value */
+
+/* RTC shift control register */
+
+#define RTC_SHIFTR_SUBFS_SHIFT (0) /* Bits 0-14: Subtract a fraction of a second */
+#define RTC_SHIFTR_SUBFS_MASK (0x7ffff << RTC_SHIFTR_SUBFS_SHIFT)
+#define RTC_SHIFTR_ADD1S (1 << 31) /* Bit 31: Add one second */
+
+/* RTC time stamp time register */
+
+#define RTC_TSTR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format. */
+#define RTC_TSTR_SU_MASK (15 << RTC_TSTR_SU_SHIFT)
+#define RTC_TSTR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format. */
+#define RTC_TSTR_ST_MASK (7 << RTC_TSTR_ST_SHIFT)
+#define RTC_TSTR_MNU_SHIFT (8) /* Bits 8-11: Minute units in BCD format. */
+#define RTC_TSTR_MNU_MASK (15 << RTC_TSTR_MNU_SHIFT)
+#define RTC_TSTR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format. */
+#define RTC_TSTR_MNT_MASK (7 << RTC_TSTR_MNT_SHIFT)
+#define RTC_TSTR_HU_SHIFT (16) /* Bits 16-19: Hour units in BCD format. */
+#define RTC_TSTR_HU_MASK (15 << RTC_TSTR_HU_SHIFT)
+#define RTC_TSTR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format. */
+#define RTC_TSTR_HT_MASK (3 << RTC_TSTR_HT_SHIFT)
+#define RTC_TSTR_PM (1 << 22) /* Bit 22: AM/PM notation */
+
+/* RTC time stamp date register */
+
+#define RTC_TSDR_DU_SHIFT (0) /* Bit 0-3: Date units in BCD format */
+#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT) */
+#define RTC_TSDR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */
+#define RTC_TSDR_DT_MASK (3 << RTC_TSDR_DT_SHIFT)
+#define RTC_TSDR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */
+#define RTC_TSDR_MU_MASK (xx << RTC_TSDR_MU_SHIFT)
+#define RTC_TSDR_MT (1 << 12) /* Bit 12: Month tens in BCD format */
+#define RTC_TSDR_WDU_SHIFT (13) /* Bits 13-15: Week day units */
+#define RTC_TSDR_WDU_MASK (7 << RTC_TSDR_WDU_SHIFT)
+
+/* RTC timestamp sub second register */
+
+#define RTC_TSSSR_MASK (0xffff) /* Bits 0-15: Sub second value */
+
+/* RTC calibration register */
+
+#define RTC_CALR_
+
+/* RTC tamper and alternate function configuration register */
+
+#define RTC_TAFCR_CALM_SHIFT (0) /* Bits 0-8: Calibration minus */
+#define RTC_TAFCR_CALM_MASK (0x1ff << RTC_TAFCR_CALM_SHIFT)
+#define RTC_TAFCR_CALW16 (1 << 13) /* Bit 13: Use a 16-second calibration cycle period */
+#define RTC_TAFCR_CALW8 (1 << 14) /* Bit 14: Use an 8-second calibration cycle period */
+#define RTC_TAFCR_CALP (1 << 15) /* Bit 15: Increase frequency of RTC by 488.5 ppm */
+
+/* RTC alarm A/B sub second register */
+
+#define RTC_ALRMSSR_SS_SHIFT (0) /* Bits 0-15: Sub second value */
+#define RTC_ALRMSSR_SS_MASK (0xffff << RTC_ALRMSSR_SS_SHIFT)
+#define RTC_ALRMSSR_MASKSS_SHIFT (0) /* Bits 24-27: Mask the most-significant bits starting at this bit */
+#define RTC_ALRMSSR_MASKSS_MASK (0xffff << RTC_ALRMSSR_SS_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F20XXX_RTC_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_vectors.h b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_vectors.h
new file mode 100644
index 000000000..12fb5565c
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f20xxx_vectors.h
@@ -0,0 +1,141 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f20xxx_vectors.h
+ *
+ * Copyright (C) 2012 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.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ * Pre-processor definitions
+ ************************************************************************************/
+
+/* This file is included by stm32_vectors.S. It provides the macro VECTOR that
+ * supplies ach STM32F20xxx vector in terms of a (lower-case) ISR label and an
+ * (upper-case) IRQ number as defined in arch/arm/include/stm32/stm32f20xxx_irq.h.
+ * stm32_vectors.S will defined the VECTOR in different ways in order to generate
+ * the interrupt vectors and handlers in their final form.
+ */
+
+/* If the common ARMv7-M vector handling is used, then all it needs is the following
+ * definition that provides the number of supported vectors.
+ */
+
+#ifdef CONFIG_ARMV7M_CMNVECTOR
+
+/* Reserve 82 interrupt table entries for I/O interrupts. */
+
+# define ARMV7M_PERIPHERAL_INTERRUPTS 82
+
+#else
+
+VECTOR(stm32_wwdg, STM32_IRQ_WWDG) /* Vector 16+0: Window Watchdog interrupt */
+VECTOR(stm32_pvd, STM32_IRQ_PVD) /* Vector 16+1: PVD through EXTI Line detection interrupt */
+VECTOR(stm32_tamper, STM32_IRQ_TAMPER) /* Vector 16+2: Tamper and time stamp interrupts */
+VECTOR(stm32_rtc_wkup, STM32_IRQ_RTC_WKUP) /* Vector 16+3: RTC global interrupt */
+VECTOR(stm32_flash, STM32_IRQ_FLASH) /* Vector 16+4: Flash global interrupt */
+VECTOR(stm32_rcc, STM32_IRQ_RCC) /* Vector 16+5: RCC global interrupt */
+VECTOR(stm32_exti0, STM32_IRQ_EXTI0) /* Vector 16+6: EXTI Line 0 interrupt */
+VECTOR(stm32_exti1, STM32_IRQ_EXTI1) /* Vector 16+7: EXTI Line 1 interrupt */
+VECTOR(stm32_exti2, STM32_IRQ_EXTI2) /* Vector 16+8: EXTI Line 2 interrupt */
+VECTOR(stm32_exti3, STM32_IRQ_EXTI3) /* Vector 16+9: EXTI Line 3 interrupt */
+VECTOR(stm32_exti4, STM32_IRQ_EXTI4) /* Vector 16+10: EXTI Line 4 interrupt */
+VECTOR(stm32_dma1s0, STM32_IRQ_DMA1S0) /* Vector 16+11: DMA1 Stream 0 global interrupt */
+VECTOR(stm32_dma1s1, STM32_IRQ_DMA1S1) /* Vector 16+12: DMA1 Stream 1 global interrupt */
+VECTOR(stm32_dma1s2, STM32_IRQ_DMA1S2) /* Vector 16+13: DMA1 Stream 2 global interrupt */
+VECTOR(stm32_dma1s3, STM32_IRQ_DMA1S3) /* Vector 16+14: DMA1 Stream 3 global interrupt */
+VECTOR(stm32_dma1s4, STM32_IRQ_DMA1S4) /* Vector 16+15: DMA1 Stream 4 global interrupt */
+VECTOR(stm32_dma1s5, STM32_IRQ_DMA1S5) /* Vector 16+16: DMA1 Stream 5 global interrupt */
+VECTOR(stm32_dma1s6, STM32_IRQ_DMA1S6) /* Vector 16+17: DMA1 Stream 6 global interrupt */
+VECTOR(stm32_adc, STM32_IRQ_ADC) /* Vector 16+18: ADC1, ADC2, and ADC3 global interrupt */
+VECTOR(stm32_can1tx, STM32_IRQ_CAN1TX) /* Vector 16+19: CAN1 TX interrupts */
+VECTOR(stm32_can1rx0, STM32_IRQ_CAN1RX0) /* Vector 16+20: CAN1 RX0 interrupts */
+VECTOR(stm32_can1rx1, STM32_IRQ_CAN1RX1) /* Vector 16+21: CAN1 RX1 interrupt */
+VECTOR(stm32_can1sce, STM32_IRQ_CAN1SCE) /* Vector 16+22: CAN1 SCE interrupt */
+VECTOR(stm32_exti95, STM32_IRQ_EXTI95) /* Vector 16+23: EXTI Line[9:5] interrupts */
+VECTOR(stm32_tim1brk, STM32_IRQ_TIM1BRK) /* Vector 16+24: TIM1 Break interrupt/TIM9 global interrupt */
+VECTOR(stm32_tim1up, STM32_IRQ_TIM1UP) /* Vector 16+25: TIM1 Update interrupt/TIM10 global interrupt */
+VECTOR(stm32_tim1trgcom, STM32_IRQ_TIM1TRGCOM) /* Vector 16+26: TIM1 Trigger and Commutation interrupts/TIM11 global interrupt */
+VECTOR(stm32_tim1cc, STM32_IRQ_TIM1CC) /* Vector 16+27: TIM1 Capture Compare interrupt */
+VECTOR(stm32_tim2, STM32_IRQ_TIM2) /* Vector 16+28: TIM2 global interrupt */
+VECTOR(stm32_tim3, STM32_IRQ_TIM3) /* Vector 16+29: TIM3 global interrupt */
+VECTOR(stm32_tim4, STM32_IRQ_TIM4) /* Vector 16+30: TIM4 global interrupt */
+VECTOR(stm32_i2c1ev, STM32_IRQ_I2C1EV) /* Vector 16+31: I2C1 event interrupt */
+VECTOR(stm32_i2c1er, STM32_IRQ_I2C1ER) /* Vector 16+32: I2C1 error interrupt */
+VECTOR(stm32_i2c2ev, STM32_IRQ_I2C2EV) /* Vector 16+33: I2C2 event interrupt */
+VECTOR(stm32_i2c2er, STM32_IRQ_I2C2ER) /* Vector 16+34: I2C2 error interrupt */
+VECTOR(stm32_spi1, STM32_IRQ_SPI1) /* Vector 16+35: SPI1 global interrupt */
+VECTOR(stm32_spi2, STM32_IRQ_SPI2) /* Vector 16+36: SPI2 global interrupt */
+VECTOR(stm32_usart1, STM32_IRQ_USART1) /* Vector 16+37: USART1 global interrupt */
+VECTOR(stm32_usart2, STM32_IRQ_USART2) /* Vector 16+38: USART2 global interrupt */
+VECTOR(stm32_usart3, STM32_IRQ_USART3) /* Vector 16+39: USART3 global interrupt */
+VECTOR(stm32_exti1510, STM32_IRQ_EXTI1510) /* Vector 16+40: EXTI Line[15:10] interrupts */
+VECTOR(stm32_rtcalrm, STM32_IRQ_RTCALRM) /* Vector 16+41: RTC alarm through EXTI line interrupt */
+VECTOR(stm32_otgfswkup, STM32_IRQ_OTGFSWKUP) /* Vector 16+42: USB On-The-Go FS Wakeup through EXTI line interrupt */
+VECTOR(stm32_tim8brk, STM32_IRQ_TIM8BRK) /* Vector 16+43: TIM8 Break interrupt/TIM12 global interrupt */
+VECTOR(stm32_tim8up, STM32_IRQ_TIM8UP) /* Vector 16+44: TIM8 Update interrup/TIM13 global interrupt */
+VECTOR(stm32_tim8trgcom, STM32_IRQ_TIM8TRGCOM) /* Vector 16+45: TIM8 Trigger and Commutation interrupts/TIM14 global interrupt */
+VECTOR(stm32_tim8cc, STM32_IRQ_TIM8CC) /* Vector 16+46: TIM8 Capture Compare interrupt */
+VECTOR(stm32_dma1s7, STM32_IRQ_DMA1S7) /* Vector 16+47: DMA1 Stream 7 global interrupt */
+VECTOR(stm32_fsmc, STM32_IRQ_FSMC) /* Vector 16+48: FSMC global interrupt */
+VECTOR(stm32_sdio, STM32_IRQ_SDIO) /* Vector 16+49: SDIO global interrupt */
+VECTOR(stm32_tim5, STM32_IRQ_TIM5) /* Vector 16+50: TIM5 global interrupt */
+VECTOR(stm32_spi3, STM32_IRQ_SPI3) /* Vector 16+51: SPI3 global interrupt */
+VECTOR(stm32_uart4, STM32_IRQ_UART4) /* Vector 16+52: UART4 global interrupt */
+VECTOR(stm32_uart5, STM32_IRQ_UART5) /* Vector 16+53: UART5 global interrupt */
+VECTOR(stm32_tim6, STM32_IRQ_TIM6) /* Vector 16+54: TIM6 global interrupt/DAC1 and DAC2 underrun error interrupts */
+VECTOR(stm32_tim7, STM32_IRQ_TIM7) /* Vector 16+55: TIM7 global interrupt */
+VECTOR(stm32_dma2s0, STM32_IRQ_DMA2S0) /* Vector 16+56: DMA2 Stream 0 global interrupt */
+VECTOR(stm32_dma2s1, STM32_IRQ_DMA2S1) /* Vector 16+57: DMA2 Stream 1 global interrupt */
+VECTOR(stm32_dma2s2, STM32_IRQ_DMA2S2) /* Vector 16+58: DMA2 Stream 2 global interrupt */
+VECTOR(stm32_dma2s3, STM32_IRQ_DMA2S3) /* Vector 16+59: DMA2 Stream 3 global interrupt */
+VECTOR(stm32_dma2s4, STM32_IRQ_DMA2S4) /* Vector 16+60: DMA2 Stream 4 global interrupt */
+VECTOR(stm32_eth, STM32_IRQ_ETH) /* Vector 16+61: Ethernet global interrupt */
+VECTOR(stm32_ethwkup, STM32_IRQ_ETHWKUP) /* Vector 16+62: Ethernet Wakeup through EXTI line interrupt */
+VECTOR(stm32_can2tx, STM32_IRQ_CAN2TX) /* Vector 16+63: CAN2 TX interrupts */
+VECTOR(stm32_can2rx0, STM32_IRQ_CAN2RX0) /* Vector 16+64: CAN2 RX0 interrupts */
+VECTOR(stm32_can2rx1, STM32_IRQ_CAN2RX1) /* Vector 16+65: CAN2 RX1 interrupt */
+VECTOR(stm32_can2sce, STM32_IRQ_CAN2SCE) /* Vector 16+66: CAN2 SCE interrupt */
+VECTOR(stm32_otgfs, STM32_IRQ_OTGFS) /* Vector 16+67: USB On The Go FS global interrupt */
+VECTOR(stm32_dma2s5, STM32_IRQ_DMA2S5) /* Vector 16+68: DMA2 Stream 5 global interrupt */
+VECTOR(stm32_dma2s6, STM32_IRQ_DMA2S6) /* Vector 16+69: DMA2 Stream 6 global interrupt */
+VECTOR(stm32_dma2s7, STM32_IRQ_DMA2S7) /* Vector 16+70: DMA2 Stream 7 global interrupt */
+VECTOR(stm32_usart6, STM32_IRQ_USART6) /* Vector 16+71: USART6 global interrupt */
+VECTOR(stm32_i2c3ev, STM32_IRQ_I2C3EV) /* Vector 16+72: I2C3 event interrupt */
+VECTOR(stm32_i2c3er, STM32_IRQ_I2C3ER) /* Vector 16+73: I2C3 error interrupt */
+VECTOR(stm32_otghsep1out, STM32_IRQ_OTGHSEP1OUT) /* Vector 16+74: USB On The Go HS End Point 1 Out global interrupt */
+VECTOR(stm32_otghsep1in, STM32_IRQ_OTGHSEP1IN) /* Vector 16+75: USB On The Go HS End Point 1 In global interrupt */
+VECTOR(stm32_otghswkup, STM32_IRQ_OTGHSWKUP) /* Vector 16+76: USB On The Go HS Wakeup through EXTI interrupt */
+VECTOR(stm32_otghs, STM32_IRQ_OTGHS ) /* Vector 16+77: USB On The Go HS global interrupt */
+VECTOR(stm32_dcmi, STM32_IRQ_DCMI) /* Vector 16+78: DCMI global interrupt */
+VECTOR(stm32_cryp, STM32_IRQ_CRYP) /* Vector 16+79: CRYP crypto global interrupt */
+VECTOR(stm32_hash, STM32_IRQ_HASH) /* Vector 16+80: Hash and Rng global interrupt */
+
+#endif /* CONFIG_ARMV7M_CMNVECTOR */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_dma.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_dma.h
new file mode 100644
index 000000000..ab0cfceac
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_dma.h
@@ -0,0 +1,520 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f40xxx_dma.h
+ *
+ * Copyright (C) 2011-2012 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_STM32_CHIP_STM32F40XXX_DMA_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_DMA_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* 2 DMA controllers */
+
+#define DMA1 (0)
+#define DMA2 (1)
+
+/* 8 DMA streams */
+
+#define DMA_STREAM0 (0)
+#define DMA_STREAM1 (1)
+#define DMA_STREAM2 (2)
+#define DMA_STREAM3 (3)
+#define DMA_STREAM4 (4)
+#define DMA_STREAM5 (5)
+#define DMA_STREAM6 (6)
+#define DMA_STREAM7 (7)
+
+/* 8 DMA channels */
+
+#define DMA_CHAN0 (0)
+#define DMA_CHAN1 (1)
+#define DMA_CHAN2 (2)
+#define DMA_CHAN3 (3)
+#define DMA_CHAN4 (4)
+#define DMA_CHAN5 (5)
+#define DMA_CHAN6 (6)
+#define DMA_CHAN7 (7)
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_DMA_LISR_OFFSET 0x0000 /* DMA low interrupt status register */
+#define STM32_DMA_HISR_OFFSET 0x0004 /* DMA high interrupt status register */
+#define STM32_DMA_LIFCR_OFFSET 0x0008 /* DMA low interrupt flag clear register */
+#define STM32_DMA_HIFCR_OFFSET 0x000c /* DMA high interrupt flag clear register */
+
+#define STM32_DMA_OFFSET(n) (0x0010+0x0018*(n))
+#define STM32_DMA_SCR_OFFSET 0x0000 /* DMA stream n configuration register */
+#define STM32_DMA_SNDTR_OFFSET 0x0004 /* DMA stream n number of data register */
+#define STM32_DMA_SPAR_OFFSET 0x0008 /* DMA stream n peripheral address register */
+#define STM32_DMA_SM0AR_OFFSET 0x000c /* DMA stream n memory 0 address register */
+#define STM32_DMA_SM1AR_OFFSET 0x0010 /* DMA stream n memory 1 address register */
+#define STM32_DMA_SFCR_OFFSET 0x0014 /* DMA stream n FIFO control register */
+
+#define STM32_DMA_S0CR_OFFSET 0x0010 /* DMA stream 0 configuration register */
+#define STM32_DMA_S1CR_OFFSET 0x0028 /* DMA stream 1 configuration register */
+#define STM32_DMA_S2CR_OFFSET 0x0040 /* DMA stream 2 configuration register */
+#define STM32_DMA_S3CR_OFFSET 0x0058 /* DMA stream 3 configuration register */
+#define STM32_DMA_S4CR_OFFSET 0x0070 /* DMA stream 4 configuration register */
+#define STM32_DMA_S5CR_OFFSET 0x0088 /* DMA stream 5 configuration register */
+#define STM32_DMA_S6CR_OFFSET 0x00a0 /* DMA stream 6 configuration register */
+#define STM32_DMA_S7CR_OFFSET 0x00b8 /* DMA stream 7 configuration register */
+
+#define STM32_DMA_S0NDTR_OFFSET 0x0014 /* DMA stream 0 number of data register */
+#define STM32_DMA_S1NDTR_OFFSET 0x002c /* DMA stream 1 number of data register */
+#define STM32_DMA_S2NDTR_OFFSET 0x0044 /* DMA stream 2 number of data register */
+#define STM32_DMA_S3NDTR_OFFSET 0x005c /* DMA stream 3 number of data register */
+#define STM32_DMA_S4NDTR_OFFSET 0x0074 /* DMA stream 4 number of data register */
+#define STM32_DMA_S5NDTR_OFFSET 0x008c /* DMA stream 5 number of data register */
+#define STM32_DMA_S6NDTR_OFFSET 0x00a4 /* DMA stream 6 number of data register */
+#define STM32_DMA_S7NDTR_OFFSET 0x00bc /* DMA stream 7 number of data register */
+
+#define STM32_DMA_S0PAR_OFFSET 0x0018 /* DMA stream 0 peripheral address register */
+#define STM32_DMA_S1PAR_OFFSET 0x0030 /* DMA stream 1 peripheral address register */
+#define STM32_DMA_S2PAR_OFFSET 0x0048 /* DMA stream 2 peripheral address register */
+#define STM32_DMA_S3PAR_OFFSET 0x0060 /* DMA stream 3 peripheral address register */
+#define STM32_DMA_S4PAR_OFFSET 0x0078 /* DMA stream 4 peripheral address register */
+#define STM32_DMA_S5PAR_OFFSET 0x0090 /* DMA stream 5 peripheral address register */
+#define STM32_DMA_S6PAR_OFFSET 0x00a8 /* DMA stream 6 peripheral address register */
+#define STM32_DMA_S7PAR_OFFSET 0x00c0 /* DMA stream 7 peripheral address register */
+
+#define STM32_DMA_S0M0AR_OFFSET 0x001c /* DMA stream 0 memory 0 address register */
+#define STM32_DMA_S1M0AR_OFFSET 0x0034 /* DMA stream 1 memory 0 address register */
+#define STM32_DMA_S2M0AR_OFFSET 0x004c /* DMA stream 2 memory 0 address register */
+#define STM32_DMA_S3M0AR_OFFSET 0x0064 /* DMA stream 3 memory 0 address register */
+#define STM32_DMA_S4M0AR_OFFSET 0x007c /* DMA stream 4 memory 0 address register */
+#define STM32_DMA_S5M0AR_OFFSET 0x0094 /* DMA stream 5 memory 0 address register */
+#define STM32_DMA_S6M0AR_OFFSET 0x00ac /* DMA stream 6 memory 0 address register */
+#define STM32_DMA_S7M0AR_OFFSET 0x00c4 /* DMA stream 7 memory 0 address register */
+
+#define STM32_DMA_S0M1AR_OFFSET 0x0020 /* DMA stream 0 memory 1 address register */
+#define STM32_DMA_S1M1AR_OFFSET 0x0038 /* DMA stream 1 memory 1 address register */
+#define STM32_DMA_S2M1AR_OFFSET 0x0050 /* DMA stream 2 memory 1 address register */
+#define STM32_DMA_S3M1AR_OFFSET 0x0068 /* DMA stream 3 memory 1 address register */
+#define STM32_DMA_S4M1AR_OFFSET 0x0080 /* DMA stream 4 memory 1 address register */
+#define STM32_DMA_S5M1AR_OFFSET 0x0098 /* DMA stream 5 memory 1 address register */
+#define STM32_DMA_S6M1AR_OFFSET 0x00b0 /* DMA stream 6 memory 1 address register */
+#define STM32_DMA_S7M1AR_OFFSET 0x00c8 /* DMA stream 7 memory 1 address register */
+
+#define STM32_DMA_S0FCR_OFFSET 0x0024 /* DMA stream 0 FIFO control register */
+#define STM32_DMA_S1FCR_OFFSET 0x003c /* DMA stream 1 FIFO control register */
+#define STM32_DMA_S2FCR_OFFSET 0x0054 /* DMA stream 2 FIFO control register */
+#define STM32_DMA_S3FCR_OFFSET 0x006c /* DMA stream 3 FIFO control register */
+#define STM32_DMA_S4FCR_OFFSET 0x0084 /* DMA stream 4 FIFO control register */
+#define STM32_DMA_S5FCR_OFFSET 0x009c /* DMA stream 5 FIFO control register */
+#define STM32_DMA_S6FCR_OFFSET 0x00b4 /* DMA stream 6 FIFO control register */
+#define STM32_DMA_S7FCR_OFFSET 0x00cc /* DMA stream 7 FIFO control register */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_DMA1_LISRC (STM32_DMA1_BASE+STM32_DMA_LISR_OFFSET)
+#define STM32_DMA1_HISRC (STM32_DMA1_BASE+STM32_DMA_HISR_OFFSET)
+#define STM32_DMA1_LIFCR (STM32_DMA1_BASE+STM32_DMA_LIFCR_OFFSET)
+#define STM32_DMA1_HIFCR (STM32_DMA1_BASE+STM32_DMA_HIFCR_OFFSET)
+
+#define STM32_DMA1_SCR(n) (STM32_DMA1_BASE+STM32_DMA_SCR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0CR (STM32_DMA1_BASE+STM32_DMA_S0CR_OFFSET)
+#define STM32_DMA1_S1CR (STM32_DMA1_BASE+STM32_DMA_S1CR_OFFSET)
+#define STM32_DMA1_S2CR (STM32_DMA1_BASE+STM32_DMA_S2CR_OFFSET)
+#define STM32_DMA1_S3CR (STM32_DMA1_BASE+STM32_DMA_S3CR_OFFSET)
+#define STM32_DMA1_S4CR (STM32_DMA1_BASE+STM32_DMA_S4CR_OFFSET)
+#define STM32_DMA1_S5CR (STM32_DMA1_BASE+STM32_DMA_S5CR_OFFSET)
+#define STM32_DMA1_S6CR (STM32_DMA1_BASE+STM32_DMA_S6CR_OFFSET)
+#define STM32_DMA1_S7CR (STM32_DMA1_BASE+STM32_DMA_S7CR_OFFSET)
+
+#define STM32_DMA1_SNDTR(n) (STM32_DMA1_BASE+STM32_DMA_SNDTR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0NDTR (STM32_DMA1_BASE+STM32_DMA_S0NDTR_OFFSET)
+#define STM32_DMA1_S1NDTR (STM32_DMA1_BASE+STM32_DMA_S1NDTR_OFFSET)
+#define STM32_DMA1_S2NDTR (STM32_DMA1_BASE+STM32_DMA_S2NDTR_OFFSET)
+#define STM32_DMA1_S3NDTR (STM32_DMA1_BASE+STM32_DMA_S3NDTR_OFFSET)
+#define STM32_DMA1_S4NDTR (STM32_DMA1_BASE+STM32_DMA_S4NDTR_OFFSET)
+#define STM32_DMA1_S5NDTR (STM32_DMA1_BASE+STM32_DMA_S5NDTR_OFFSET)
+#define STM32_DMA1_S6NDTR (STM32_DMA1_BASE+STM32_DMA_S6NDTR_OFFSET)
+#define STM32_DMA1_S7NDTR (STM32_DMA1_BASE+STM32_DMA_S7NDTR_OFFSET)
+
+#define STM32_DMA1_SPAR(n) (STM32_DMA1_BASE+STM32_DMA_SPAR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0PAR (STM32_DMA1_BASE+STM32_DMA_S0PAR_OFFSET)
+#define STM32_DMA1_S1PAR (STM32_DMA1_BASE+STM32_DMA_S1PAR_OFFSET)
+#define STM32_DMA1_S2PAR (STM32_DMA1_BASE+STM32_DMA_S2PAR_OFFSET)
+#define STM32_DMA1_S3PAR (STM32_DMA1_BASE+STM32_DMA_S3PAR_OFFSET)
+#define STM32_DMA1_S4PAR (STM32_DMA1_BASE+STM32_DMA_S4PAR_OFFSET)
+#define STM32_DMA1_S5PAR (STM32_DMA1_BASE+STM32_DMA_S5PAR_OFFSET)
+#define STM32_DMA1_S6PAR (STM32_DMA1_BASE+STM32_DMA_S6PAR_OFFSET)
+#define STM32_DMA1_S7PAR (STM32_DMA1_BASE+STM32_DMA_S7PAR_OFFSET)
+
+#define STM32_DMA1_SM0AR(n) (STM32_DMA1_BASE+STM32_DMA_SM0AR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0M0AR (STM32_DMA1_BASE+STM32_DMA_S0M0AR_OFFSET)
+#define STM32_DMA1_S1M0AR (STM32_DMA1_BASE+STM32_DMA_S1M0AR_OFFSET)
+#define STM32_DMA1_S2M0AR (STM32_DMA1_BASE+STM32_DMA_S2M0AR_OFFSET)
+#define STM32_DMA1_S3M0AR (STM32_DMA1_BASE+STM32_DMA_S3M0AR_OFFSET)
+#define STM32_DMA1_S4M0AR (STM32_DMA1_BASE+STM32_DMA_S4M0AR_OFFSET)
+#define STM32_DMA1_S5M0AR (STM32_DMA1_BASE+STM32_DMA_S5M0AR_OFFSET)
+#define STM32_DMA1_S6M0AR (STM32_DMA1_BASE+STM32_DMA_S6M0AR_OFFSET)
+#define STM32_DMA1_S7M0AR (STM32_DMA1_BASE+STM32_DMA_S7M0AR_OFFSET)
+
+#define STM32_DMA1_SM1AR(n) (STM32_DMA1_BASE+STM32_DMA_SM1AR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0M1AR (STM32_DMA1_BASE+STM32_DMA_S0M1AR_OFFSET)
+#define STM32_DMA1_S1M1AR (STM32_DMA1_BASE+STM32_DMA_S1M1AR_OFFSET)
+#define STM32_DMA1_S2M1AR (STM32_DMA1_BASE+STM32_DMA_S2M1AR_OFFSET)
+#define STM32_DMA1_S3M1AR (STM32_DMA1_BASE+STM32_DMA_S3M1AR_OFFSET)
+#define STM32_DMA1_S4M1AR (STM32_DMA1_BASE+STM32_DMA_S4M1AR_OFFSET)
+#define STM32_DMA1_S5M1AR (STM32_DMA1_BASE+STM32_DMA_S5M1AR_OFFSET)
+#define STM32_DMA1_S6M1AR (STM32_DMA1_BASE+STM32_DMA_S6M1AR_OFFSET)
+#define STM32_DMA1_S7M1AR (STM32_DMA1_BASE+STM32_DMA_S7M1AR_OFFSET)
+
+#define STM32_DMA1_SFCR(n) (STM32_DMA1_BASE+STM32_DMA_SFCR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA1_S0FCR (STM32_DMA1_BASE+STM32_DMA_S0FCR_OFFSET)
+#define STM32_DMA1_S1FCR (STM32_DMA1_BASE+STM32_DMA_S1FCR_OFFSET)
+#define STM32_DMA1_S2FCR (STM32_DMA1_BASE+STM32_DMA_S2FCR_OFFSET)
+#define STM32_DMA1_S3FCR (STM32_DMA1_BASE+STM32_DMA_S3FCR_OFFSET)
+#define STM32_DMA1_S4FCR (STM32_DMA1_BASE+STM32_DMA_S4FCR_OFFSET)
+#define STM32_DMA1_S5FCR (STM32_DMA1_BASE+STM32_DMA_S5FCR_OFFSET)
+#define STM32_DMA1_S6FCR (STM32_DMA1_BASE+STM32_DMA_S6FCR_OFFSET)
+#define STM32_DMA1_S7FCR (STM32_DMA1_BASE+STM32_DMA_S7FCR_OFFSET)
+
+#define STM32_DMA2_LISRC (STM32_DMA2_BASE+STM32_DMA_LISR_OFFSET)
+#define STM32_DMA2_HISRC (STM32_DMA2_BASE+STM32_DMA_HISR_OFFSET)
+#define STM32_DMA2_LIFCR (STM32_DMA2_BASE+STM32_DMA_LIFCR_OFFSET)
+#define STM32_DMA2_HIFCR (STM32_DMA2_BASE+STM32_DMA_HIFCR_OFFSET)
+
+#define STM32_DMA2_SCR(n) (STM32_DMA2_BASE+STM32_DMA_SCR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0CR (STM32_DMA2_BASE+STM32_DMA_S0CR_OFFSET)
+#define STM32_DMA2_S1CR (STM32_DMA2_BASE+STM32_DMA_S1CR_OFFSET)
+#define STM32_DMA2_S2CR (STM32_DMA2_BASE+STM32_DMA_S2CR_OFFSET)
+#define STM32_DMA2_S3CR (STM32_DMA2_BASE+STM32_DMA_S3CR_OFFSET)
+#define STM32_DMA2_S4CR (STM32_DMA2_BASE+STM32_DMA_S4CR_OFFSET)
+#define STM32_DMA2_S5CR (STM32_DMA2_BASE+STM32_DMA_S5CR_OFFSET)
+#define STM32_DMA2_S6CR (STM32_DMA2_BASE+STM32_DMA_S6CR_OFFSET)
+#define STM32_DMA2_S7CR (STM32_DMA2_BASE+STM32_DMA_S7CR_OFFSET)
+
+#define STM32_DMA2_SNDTR(n) (STM32_DMA2_BASE+STM32_DMA_SNDTR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0NDTR (STM32_DMA2_BASE+STM32_DMA_S0NDTR_OFFSET)
+#define STM32_DMA2_S1NDTR (STM32_DMA2_BASE+STM32_DMA_S1NDTR_OFFSET)
+#define STM32_DMA2_S2NDTR (STM32_DMA2_BASE+STM32_DMA_S2NDTR_OFFSET)
+#define STM32_DMA2_S3NDTR (STM32_DMA2_BASE+STM32_DMA_S3NDTR_OFFSET)
+#define STM32_DMA2_S4NDTR (STM32_DMA2_BASE+STM32_DMA_S4NDTR_OFFSET)
+#define STM32_DMA2_S5NDTR (STM32_DMA2_BASE+STM32_DMA_S5NDTR_OFFSET)
+#define STM32_DMA2_S6NDTR (STM32_DMA2_BASE+STM32_DMA_S6NDTR_OFFSET)
+#define STM32_DMA2_S7NDTR (STM32_DMA2_BASE+STM32_DMA_S7NDTR_OFFSET)
+
+#define STM32_DMA2_SPAR(n) (STM32_DMA2_BASE+STM32_DMA_SPAR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0PAR (STM32_DMA2_BASE+STM32_DMA_S0PAR_OFFSET)
+#define STM32_DMA2_S1PAR (STM32_DMA2_BASE+STM32_DMA_S1PAR_OFFSET)
+#define STM32_DMA2_S2PAR (STM32_DMA2_BASE+STM32_DMA_S2PAR_OFFSET)
+#define STM32_DMA2_S3PAR (STM32_DMA2_BASE+STM32_DMA_S3PAR_OFFSET)
+#define STM32_DMA2_S4PAR (STM32_DMA2_BASE+STM32_DMA_S4PAR_OFFSET)
+#define STM32_DMA2_S5PAR (STM32_DMA2_BASE+STM32_DMA_S5PAR_OFFSET)
+#define STM32_DMA2_S6PAR (STM32_DMA2_BASE+STM32_DMA_S6PAR_OFFSET)
+#define STM32_DMA2_S7PAR (STM32_DMA2_BASE+STM32_DMA_S7PAR_OFFSET)
+
+#define STM32_DMA2_SM0AR(n) (STM32_DMA2_BASE+STM32_DMA_SM0AR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0M0AR (STM32_DMA2_BASE+STM32_DMA_S0M0AR_OFFSET)
+#define STM32_DMA2_S1M0AR (STM32_DMA2_BASE+STM32_DMA_S1M0AR_OFFSET)
+#define STM32_DMA2_S2M0AR (STM32_DMA2_BASE+STM32_DMA_S2M0AR_OFFSET)
+#define STM32_DMA2_S3M0AR (STM32_DMA2_BASE+STM32_DMA_S3M0AR_OFFSET)
+#define STM32_DMA2_S4M0AR (STM32_DMA2_BASE+STM32_DMA_S4M0AR_OFFSET)
+#define STM32_DMA2_S5M0AR (STM32_DMA2_BASE+STM32_DMA_S5M0AR_OFFSET)
+#define STM32_DMA2_S6M0AR (STM32_DMA2_BASE+STM32_DMA_S6M0AR_OFFSET)
+#define STM32_DMA2_S7M0AR (STM32_DMA2_BASE+STM32_DMA_S7M0AR_OFFSET)
+
+#define STM32_DMA2_SM1AR(n) (STM32_DMA2_BASE+STM32_DMA_SM1AR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0M1AR (STM32_DMA2_BASE+STM32_DMA_S0M1AR_OFFSET)
+#define STM32_DMA2_S1M1AR (STM32_DMA2_BASE+STM32_DMA_S1M1AR_OFFSET)
+#define STM32_DMA2_S2M1AR (STM32_DMA2_BASE+STM32_DMA_S2M1AR_OFFSET)
+#define STM32_DMA2_S3M1AR (STM32_DMA2_BASE+STM32_DMA_S3M1AR_OFFSET)
+#define STM32_DMA2_S4M1AR (STM32_DMA2_BASE+STM32_DMA_S4M1AR_OFFSET)
+#define STM32_DMA2_S5M1AR (STM32_DMA2_BASE+STM32_DMA_S5M1AR_OFFSET)
+#define STM32_DMA2_S6M1AR (STM32_DMA2_BASE+STM32_DMA_S6M1AR_OFFSET)
+#define STM32_DMA2_S7M1AR (STM32_DMA2_BASE+STM32_DMA_S7M1AR_OFFSET)
+
+#define STM32_DMA2_SFCR(n) (STM32_DMA2_BASE+STM32_DMA_SFCR_OFFSET+STM32_DMA_OFFSET(n))
+#define STM32_DMA2_S0FCR (STM32_DMA2_BASE+STM32_DMA_S0FCR_OFFSET)
+#define STM32_DMA2_S1FCR (STM32_DMA2_BASE+STM32_DMA_S1FCR_OFFSET)
+#define STM32_DMA2_S2FCR (STM32_DMA2_BASE+STM32_DMA_S2FCR_OFFSET)
+#define STM32_DMA2_S3FCR (STM32_DMA2_BASE+STM32_DMA_S3FCR_OFFSET)
+#define STM32_DMA2_S4FCR (STM32_DMA2_BASE+STM32_DMA_S4FCR_OFFSET)
+#define STM32_DMA2_S5FCR (STM32_DMA2_BASE+STM32_DMA_S5FCR_OFFSET)
+#define STM32_DMA2_S6FCR (STM32_DMA2_BASE+STM32_DMA_S6FCR_OFFSET)
+#define STM32_DMA2_S7FCR (STM32_DMA2_BASE+STM32_DMA_S7FCR_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+#define DMA_STREAM_MASK 0x3f
+#define DMA_STREAM_FEIF_BIT (1 << 0) /* Bit 0: Stream FIFO error interrupt flag */
+#define DMA_STREAM_DMEIF_BIT (1 << 2) /* Bit 2: Stream direct mode error interrupt flag */
+#define DMA_STREAM_TEIF_BIT (1 << 3) /* Bit 3: Stream Transfer Error flag */
+#define DMA_STREAM_HTIF_BIT (1 << 4) /* Bit 4: Stream Half Transfer flag */
+#define DMA_STREAM_TCIF_BIT (1 << 5) /* Bit 5: Stream Transfer Complete flag */
+
+/* DMA interrupt status register and interrupt flag clear register field defintions */
+
+#define DMA_INT_STREAM0_SHIFT (0) /* Bits 0-5: DMA Stream 0 interrupt */
+#define DMA_INT_STREAM0_MASK (DMA_STREAM_MASK << DMA_INT_STREAM0_SHIFT)
+#define DMA_INT_STREAM1_SHIFT (6) /* Bits 6-11: DMA Stream 1 interrupt */
+#define DMA_INT_STREAM1_MASK (DMA_STREAM_MASK << DMA_INT_STREAM1_SHIFT)
+#define DMA_INT_STREAM2_SHIFT (16) /* Bits 16-21: DMA Stream 2 interrupt */
+#define DMA_INT_STREAM2_MASK (DMA_STREAM_MASK << DMA_INT_STREAM2_SHIFT)
+#define DMA_INT_STREAM3_SHIFT (22) /* Bits 22-27: DMA Stream 3 interrupt */
+#define DMA_INT_STREAM3_MASK (DMA_STREAM_MASK << DMA_INT_STREAM3_SHIFT)
+
+#define DMA_INT_STREAM4_SHIFT (0) /* Bits 0-5: DMA Stream 4 interrupt */
+#define DMA_INT_STREAM4_MASK (DMA_STREAM_MASK << DMA_INT_STREAM4_SHIFT)
+#define DMA_INT_STREAM5_SHIFT (6) /* Bits 6-11: DMA Stream 5 interrupt */
+#define DMA_INT_STREAM5_MASK (DMA_STREAM_MASK << DMA_INT_STREAM5_SHIFT)
+#define DMA_INT_STREAM6_SHIFT (16) /* Bits 16-21: DMA Stream 6 interrupt */
+#define DMA_INT_STREAM6_MASK (DMA_STREAM_MASK << DMA_INT_STREAM6_SHIFT)
+#define DMA_INT_STREAM7_SHIFT (22) /* Bits 22-27: DMA Stream 7 interrupt */
+#define DMA_INT_STREAM7_MASK (DMA_STREAM_MASK << DMA_INT_STREAM7_SHIFT)
+
+/* DMA stream configuration register */
+
+#define DMA_SCR_EN (1 << 0) /* Bit 0: Stream enable */
+#define DMA_SCR_DMEIE (1 << 1) /* Bit 1: Direct mode error interrupt enable */
+#define DMA_SCR_TEIE (1 << 2) /* Bit 2: Transfer error interrupt enable */
+#define DMA_SCR_HTIE (1 << 3) /* Bit 3: Half Transfer interrupt enable */
+#define DMA_SCR_TCIE (1 << 4) /* Bit 4: Transfer complete interrupt enable */
+#define DMA_SCR_PFCTRL (1 << 5) /* Bit 5: Peripheral flow controller */
+#define DMA_SCR_DIR_SHIFT (6) /* Bits 6-7: Data transfer direction */
+#define DMA_SCR_DIR_MASK (3 << DMA_SCR_DIR_SHIFT)
+# define DMA_SCR_DIR_P2M (0 << DMA_SCR_DIR_SHIFT) /* 00: Peripheral-to-memory */
+# define DMA_SCR_DIR_M2P (1 << DMA_SCR_DIR_SHIFT) /* 01: Memory-to-peripheral */
+# define DMA_SCR_DIR_M2M (2 << DMA_SCR_DIR_SHIFT) /* 10: Memory-to-memory */
+#define DMA_SCR_CIRC (1 << 8) /* Bit 8: Circular mode */
+#define DMA_SCR_PINC (1 << 9) /* Bit 9: Peripheral increment mode */
+#define DMA_SCR_MINC (1 << 10) /* Bit 10: Memory increment mode */
+#define DMA_SCR_PSIZE_SHIFT (11) /* Bits 11-12: Peripheral size */
+#define DMA_SCR_PSIZE_MASK (3 << DMA_SCR_PSIZE_SHIFT)
+# define DMA_SCR_PSIZE_8BITS (0 << DMA_SCR_PSIZE_SHIFT) /* 00: 8-bits */
+# define DMA_SCR_PSIZE_16BITS (1 << DMA_SCR_PSIZE_SHIFT) /* 01: 16-bits */
+# define DMA_SCR_PSIZE_32BITS (2 << DMA_SCR_PSIZE_SHIFT) /* 10: 32-bits */
+#define DMA_SCR_MSIZE_SHIFT (13) /* Bits 13-14: Memory size */
+#define DMA_SCR_MSIZE_MASK (3 << DMA_SCR_MSIZE_SHIFT)
+# define DMA_SCR_MSIZE_8BITS (0 << DMA_SCR_MSIZE_SHIFT) /* 00: 8-bits */
+# define DMA_SCR_MSIZE_16BITS (1 << DMA_SCR_MSIZE_SHIFT) /* 01: 16-bits */
+# define DMA_SCR_MSIZE_32BITS (2 << DMA_SCR_MSIZE_SHIFT) /* 10: 32-bits */
+#define DMA_SCR_PINCOS (1 << 15) /* Bit 15: Peripheral increment offset size */
+#define DMA_SCR_PL_SHIFT (16) /* Bits 16-17: Stream Priority level */
+#define DMA_SCR_PL_MASK (3 << DMA_SCR_PL_SHIFT)
+# define DMA_SCR_PRILO (0 << DMA_SCR_PL_SHIFT) /* 00: Low */
+# define DMA_SCR_PRIMED (1 << DMA_SCR_PL_SHIFT) /* 01: Medium */
+# define DMA_SCR_PRIHI (2 << DMA_SCR_PL_SHIFT) /* 10: High */
+# define DMA_SCR_PRIVERYHI (3 << DMA_SCR_PL_SHIFT) /* 11: Very high */
+#define DMA_SCR_DBM (1 << 18) /* Bit 15: Double buffer mode */
+#define DMA_SCR_CT (1 << 19) /* Bit 19: Current target */
+#define DMA_SCR_PBURST_SHIFT (21) /* Bits 21-22: Peripheral burst transfer configuration */
+#define DMA_SCR_PBURST_MASK (3 << DMA_SCR_PBURST_SHIFT)
+# define DMA_SCR_PBURST_SINGLE (0 << DMA_SCR_PBURST_SHIFT) /* 00: Single transfer */
+# define DMA_SCR_PBURST_INCR4 (1 << DMA_SCR_PBURST_SHIFT) /* 01: Incremental burst of 4 beats */
+# define DMA_SCR_PBURST_INCR8 (2 << DMA_SCR_PBURST_SHIFT) /* 10: Incremental burst of 8 beats */
+# define DMA_SCR_PBURST_INCR16 (3 << DMA_SCR_PBURST_SHIFT) /* 11: Incremental burst of 16 beats */
+#define DMA_SCR_MBURST_SHIFT (23) /* Bits 23-24: Memory burst transfer configuration */
+#define DMA_SCR_MBURST_MASK (3 << DMA_SCR_MBURST_SHIFT)
+# define DMA_SCR_MBURST_SINGLE (0 << DMA_SCR_MBURST_SHIFT) /* 00: Single transfer */
+# define DMA_SCR_MBURST_INCR4 (1 << DMA_SCR_MBURST_SHIFT) /* 01: Incremental burst of 4 beats */
+# define DMA_SCR_MBURST_INCR8 (2 << DMA_SCR_MBURST_SHIFT) /* 10: Incremental burst of 8 beats */
+# define DMA_SCR_MBURST_INCR16 (3 << DMA_SCR_MBURST_SHIFT) /* 11: Incremental burst of 16 beats */
+#define DMA_SCR_CHSEL_SHIFT (25) /* Bits 25-27: Channel selection */
+#define DMA_SCR_CHSEL_MASK (7 << DMA_SCR_CHSEL_SHIFT)
+# define DMA_SCR_CHSEL(n) ((n) << DMA_SCR_CHSEL_SHIFT)
+
+#define DMA_SCR_ALLINTS (DMA_SCR_DMEIE|DMA_SCR_TEIE|DMA_SCR_HTIE|DMA_SCR_TCIE)
+
+/* DMA stream number of data register */
+
+#define DMA_SNDTR_NDT_SHIFT (0) /* Bits 15-0: Number of data to Transfer */
+#define DMA_SNDTR_NDT_MASK (0xffff << DMA_SNDTR_NDT_SHIFT)
+
+/* DMA stream n FIFO control register */
+
+#define DMA_SFCR_FTH_SHIFT (0) /* Bits 0-1: FIFO threshold selection */
+#define DMA_SFCR_FTH_MASK (3 << DMA_SFCR_FTH_SHIFT)
+# define DMA_SFCR_FTH_QUARTER (0 << DMA_SFCR_FTH_SHIFT) /* 1/4 full FIFO */
+# define DMA_SFCR_FTH_HALF (1 << DMA_SFCR_FTH_SHIFT) /* 1/2 full FIFO */
+# define DMA_SFCR_FTH_3QUARTER (2 << DMA_SFCR_FTH_SHIFT) /* 3/4 full FIFO */
+# define DMA_SFCR_FTH_FULL (3 << DMA_SFCR_FTH_SHIFT) /* full FIFO */
+#define DMA_SFCR_DMDIS (1 << 2) /* Bit 2: Direct mode disable */
+#define DMA_SFCR_FS_SHIFT (3) /* Bits 3-5: FIFO status */
+#define DMA_SFCR_FS_MASK (7 << DMA_SFCR_FS_SHIFT)
+# define DMA_SFCR_FS_QUARTER (0 << DMA_SFCR_FS_SHIFT) /* 0 < fifo_level < 1/4 */
+# define DMA_SFCR_FS_HALF (1 << DMA_SFCR_FS_SHIFT) /* 1/4 = fifo_level < 1/2 */
+# define DMA_SFCR_FS_3QUARTER (2 << DMA_SFCR_FS_SHIFT) /* 1/2 = fifo_level < 3/4 */
+# define DMA_SFCR_FS_ALMOSTFULL (3 << DMA_SFCR_FS_SHIFT) /* 3/4 = fifo_level < full */
+# define DMA_SFCR_FS_EMPTY (4 << DMA_SFCR_FS_SHIFT) /* FIFO is empty */
+# define DMA_SFCR_FS_FULL (5 << DMA_SFCR_FS_SHIFT) /* FIFO is full */
+ /* Bit 6: Reserved */
+#define DMA_SFCR_FEIE (1 << 7) /* Bit 7: FIFO error interrupt enable */
+ /* Bits 8-31: Reserved */
+
+/* DMA Stream mapping. Each DMA stream has a mapping to several possible
+ * sources/sinks of data. The requests from peripherals assigned to a stream
+ * are simply OR'ed together before entering the DMA block. This means that only
+ * one request on a given stream can be enabled at once.
+ *
+ * Alternative stream selections are provided with a numeric suffix like _1, _2, etc.
+ * The DMA driver, however, will use the pin selection without the numeric suffix.
+ * Additional definitions are required in the board.h file. For example, if
+ * SPI3_RX connects via DMA STREAM0, then following should be application-specific
+ * mapping should be used:
+ *
+ * #define DMAMAP_SPI3_RX DMAMAP_SPI3_RX_1
+ */
+
+#define STM32_DMA_MAP(d,s,c) ((d) << 6 | (s) << 3 | (c))
+#define STM32_DMA_CONTROLLER(m) (((m) >> 6) & 1)
+#define STM32_DMA_STREAM(m) (((m) >> 3) & 7)
+#define STM32_DMA_CHANNEL(m) ((m) & 7)
+
+#define DMAMAP_SPI3_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN0)
+#define DMAMAP_SPI3_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN0)
+#define DMAMAP_SPI2_RX STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN0)
+#define DMAMAP_SPI2_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN0)
+#define DMAMAP_SPI3_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN0)
+#define DMAMAP_SPI3_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN0)
+
+#define DMAMAP_I2C1_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN1)
+#define DMAMAP_TIM7_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN1)
+#define DMAMAP_TIM7_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN1)
+#define DMAMAP_I2C1_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN1)
+#define DMAMAP_I2C1_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN1)
+#define DMAMAP_I2C1_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN1)
+
+#define DMAMAP_TIM4_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN2)
+#define DMAMAP_I2S2_EXT_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN2)
+#define DMAMAP_TIM4_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN2)
+#define DMAMAP_I2S2_EXT_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN2)
+#define DMAMAP_I2S3_EXT_TX STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN2)
+#define DMAMAP_TIM4_UP STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN2)
+#define DMAMAP_TIM4_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN2)
+
+#define DMAMAP_I2S3_EXT_RX STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN3)
+#define DMAMAP_TIM2_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN3)
+#define DMAMAP_TIM2_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN3)
+#define DMAMAP_I2C3_RX STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN3)
+#define DMAMAP_I2S2_EXT_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN3)
+#define DMAMAP_I2C3_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN3)
+#define DMAMAP_TIM2_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN3)
+#define DMAMAP_TIM2_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN3)
+#define DMAMAP_TIM2_CH4_1 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN3)
+#define DMAMAP_TIM2_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN3)
+#define DMAMAP_TIM2_CH4_2 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN3)
+
+#define DMAMAP_UART5_RX STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN4)
+#define DMAMAP_USART3_RX STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN4)
+#define DMAMAP_UART4_RX STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN4)
+#define DMAMAP_USART3_TX_1 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN4)
+#define DMAMAP_UART4_TX STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN4)
+#define DMAMAP_USART2_RX STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN4)
+#define DMAMAP_USART2_TX STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN4)
+#define DMAMAP_UART5_TX STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN4)
+
+#define DMAMAP_TIM3_CH4 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN5)
+#define DMAMAP_TIM3_UP STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN5)
+#define DMAMAP_TIM3_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN5)
+#define DMAMAP_TIM3_TRIG STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN5)
+#define DMAMAP_TIM3_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN5)
+#define DMAMAP_TIM3_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN5)
+
+#define DMAMAP_TIM5_CH3 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN6)
+#define DMAMAP_TIM5_UP_1 STM32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN6)
+#define DMAMAP_TIM5_CH4_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN6)
+#define DMAMAP_TIM5_TRIG_1 STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN6)
+#define DMAMAP_TIM5_CH1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN6)
+#define DMAMAP_TIM5_CH4_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN6)
+#define DMAMAP_TIM5_TRIG_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN6)
+#define DMAMAP_TIM5_CH2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN6)
+#define DMAMAP_TIM5_UP_2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN6)
+
+#define DMAMAP_TIM6_UP STM32_DMA_MAP(DMA1,DMA_STREAM1,DMA_CHAN7)
+#define DMAMAP_I2C2_RX_1 STM32_DMA_MAP(DMA1,DMA_STREAM2,DMA_CHAN7)
+#define DMAMAP_I2C2_RX_2 STM32_DMA_MAP(DMA1,DMA_STREAM3,DMA_CHAN7)
+#define DMAMAP_USART3_TX_2 STM32_DMA_MAP(DMA1,DMA_STREAM4,DMA_CHAN7)
+#define DMAMAP_DAC1 STM32_DMA_MAP(DMA1,DMA_STREAM5,DMA_CHAN7)
+#define DMAMAP_DAC2 STM32_DMA_MAP(DMA1,DMA_STREAM6,DMA_CHAN7)
+#define DMAMAP_I2C2_TX STM32_DMA_MAP(DMA1,DMA_STREAM7,DMA_CHAN7)
+
+#define DMAMAP_ADC1_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN0)
+#define DMAMAP_TIM8_CH1_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0)
+#define DMAMAP_TIM8_CH2_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0)
+#define DMAMAP_TIM8_CH3_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN0)
+#define DMAMAP_ADC1_2 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN0)
+#define DMAMAP_TIM1_CH1_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0)
+#define DMAMAP_TIM1_CH2_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0)
+#define DMAMAP_TIM1_CH3_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN0)
+
+#define DMAMAP_DCMI_1 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN1)
+#define DMAMAP_ADC2_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN1)
+#define DMAMAP_ADC2_2 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN1)
+#define DMAMAP_DCMI_2 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN1)
+
+#define DMAMAP_ADC3_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN2)
+#define DMAMAP_ADC3_2 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN2)
+#define DMAMAP_CRYP_OUT STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN2)
+#define DMAMAP_CRYP_IN STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN2)
+#define DMAMAP_HASH_IN STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN2)
+
+#define DMAMAP_SPI1_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN3)
+#define DMAMAP_SPI1_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN3)
+#define DMAMAP_SPI1_TX_1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN3)
+#define DMAMAP_SPI1_TX_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN3)
+
+#define DMAMAP_USART1_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN4)
+#define DMAMAP_SDIO_1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN4)
+#define DMAMAP_USART1_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN4)
+#define DMAMAP_SDIO_2 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN4)
+#define DMAMAP_USART1_TX STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN4)
+
+#define DMAMAP_USART6_RX_1 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN5)
+#define DMAMAP_USART6_RX_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN5)
+#define DMAMAP_USART6_TX_1 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN5)
+#define DMAMAP_USART6_TX_2 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN5)
+
+#define DMAMAP_TIM1_TRIG_1 STM32_DMA_MAP(DMA2,DMA_STREAM0,DMA_CHAN6)
+#define DMAMAP_TIM1_CH1_2 STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN6)
+#define DMAMAP_TIM1_CH2_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN6)
+#define DMAMAP_TIM1_CH1 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN6)
+#define DMAMAP_TIM1_CH4 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6)
+#define DMAMAP_TIM1_TRIG_2 STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6)
+#define DMAMAP_TIM1_COM STM32_DMA_MAP(DMA2,DMA_STREAM4,DMA_CHAN6)
+#define DMAMAP_TIM1_UP STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN6)
+#define DMAMAP_TIM1_CH3_2 STM32_DMA_MAP(DMA2,DMA_STREAM6,DMA_CHAN6)
+
+#define DMAMAP_TIM8_UP STM32_DMA_MAP(DMA2,DMA_STREAM1,DMA_CHAN7)
+#define DMAMAP_TIM8_CH1_2 STM32_DMA_MAP(DMA2,DMA_STREAM2,DMA_CHAN7)
+#define DMAMAP_TIM8_CH2_2 STM32_DMA_MAP(DMA2,DMA_STREAM3,DMA_CHAN7)
+#define DMAMAP_TIM8_CH3_2 STM32_DMA_MAP(DMA2,DMA_STREAM5,DMA_CHAN7)
+#define DMAMAP_TIM8_CH4 STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7)
+#define DMAMAP_TIM8_TRIG STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7)
+#define DMAMAP_TIM8_COM STM32_DMA_MAP(DMA2,DMA_STREAM7,DMA_CHAN7)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_DMA_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_gpio.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_gpio.h
new file mode 100644
index 000000000..aa7353ed9
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_gpio.h
@@ -0,0 +1,370 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f40xxx_gpio.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_CHIP_STM32F40XXX_GPIO_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_GPIO_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#define STM32_NGPIO_PORTS ((STM32_NGPIO + 15) >> 4)
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_GPIO_MODER_OFFSET 0x0000 /* GPIO port mode register */
+#define STM32_GPIO_OTYPER_OFFSET 0x0004 /* GPIO port output type register */
+#define STM32_GPIO_OSPEED_OFFSET 0x0008 /* GPIO port output speed register */
+#define STM32_GPIO_PUPDR_OFFSET 0x000c /* GPIO port pull-up/pull-down register */
+#define STM32_GPIO_IDR_OFFSET 0x0010 /* GPIO port input data register */
+#define STM32_GPIO_ODR_OFFSET 0x0014 /* GPIO port output data register */
+#define STM32_GPIO_BSRR_OFFSET 0x0018 /* GPIO port bit set/reset register */
+#define STM32_GPIO_LCKR_OFFSET 0x001c /* GPIO port configuration lock register */
+#define STM32_GPIO_AFRL_OFFSET 0x0020 /* GPIO alternate function low register */
+#define STM32_GPIO_ARFH_OFFSET 0x0024 /* GPIO alternate function high register */
+
+/* Register Addresses ***************************************************************/
+
+#if STM32_NGPIO_PORTS > 0
+# define STM32_GPIOA_MODER (STM32_GPIOA_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOA_OTYPER (STM32_GPIOA_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOA_OSPEED (STM32_GPIOA_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOA_PUPDR (STM32_GPIOA_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOA_IDR (STM32_GPIOA_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOA_ODR (STM32_GPIOA_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOA_BSRR (STM32_GPIOA_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOA_LCKR (STM32_GPIOA_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOA_AFRL (STM32_GPIOA_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOA_ARFH (STM32_GPIOA_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 1
+# define STM32_GPIOB_MODER (STM32_GPIOB_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOB_OTYPER (STM32_GPIOB_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOB_OSPEED (STM32_GPIOB_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOB_PUPDR (STM32_GPIOB_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOB_IDR (STM32_GPIOB_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOB_ODR (STM32_GPIOB_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOB_BSRR (STM32_GPIOB_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOB_LCKR (STM32_GPIOB_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOB_AFRL (STM32_GPIOB_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOB_ARFH (STM32_GPIOB_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 2
+# define STM32_GPIOC_MODER (STM32_GPIOC_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOC_OTYPER (STM32_GPIOC_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOC_OSPEED (STM32_GPIOC_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOC_PUPDR (STM32_GPIOC_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOC_IDR (STM32_GPIOC_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOC_ODR (STM32_GPIOC_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOC_BSRR (STM32_GPIOC_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOC_LCKR (STM32_GPIOC_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOC_AFRL (STM32_GPIOC_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOC_ARFH (STM32_GPIOC_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 3
+# define STM32_GPIOD_MODER (STM32_GPIOD_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOD_OTYPER (STM32_GPIOD_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOD_OSPEED (STM32_GPIOD_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOD_PUPDR (STM32_GPIOD_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOD_IDR (STM32_GPIOD_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOD_ODR (STM32_GPIOD_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOD_BSRR (STM32_GPIOD_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOD_LCKR (STM32_GPIOD_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOD_AFRL (STM32_GPIOD_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOD_ARFH (STM32_GPIOD_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 4
+# define STM32_GPIOE_MODER (STM32_GPIOE_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOE_OTYPER (STM32_GPIOE_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOE_OSPEED (STM32_GPIOE_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOE_PUPDR (STM32_GPIOE_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOE_IDR (STM32_GPIOE_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOE_ODR (STM32_GPIOE_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOE_BSRR (STM32_GPIOE_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOE_LCKR (STM32_GPIOE_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOE_AFRL (STM32_GPIOE_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOE_ARFH (STM32_GPIOE_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 5
+# define STM32_GPIOF_MODER (STM32_GPIOF_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOF_OTYPER (STM32_GPIOF_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOF_OSPEED (STM32_GPIOF_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOF_PUPDR (STM32_GPIOF_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOF_IDR (STM32_GPIOF_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOF_ODR (STM32_GPIOF_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOF_BSRR (STM32_GPIOF_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOF_LCKR (STM32_GPIOF_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOF_AFRL (STM32_GPIOF_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOF_ARFH (STM32_GPIOF_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 6
+# define STM32_GPIOG_MODER (STM32_GPIOG_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOG_OTYPER (STM32_GPIOG_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOG_OSPEED (STM32_GPIOG_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOG_PUPDR (STM32_GPIOG_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOG_IDR (STM32_GPIOG_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOG_ODR (STM32_GPIOG_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOG_BSRR (STM32_GPIOG_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOG_LCKR (STM32_GPIOG_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOG_AFRL (STM32_GPIOG_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOG_ARFH (STM32_GPIOG_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 7
+# define STM32_GPIOH_MODER (STM32_GPIOH_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOH_OTYPER (STM32_GPIOH_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOH_OSPEED (STM32_GPIOH_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOH_PUPDR (STM32_GPIOH_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOH_IDR (STM32_GPIOH_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOH_ODR (STM32_GPIOH_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOH_BSRR (STM32_GPIOH_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOH_LCKR (STM32_GPIOH_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOH_AFRL (STM32_GPIOH_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOH_ARFH (STM32_GPIOH_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+#if STM32_NGPIO_PORTS > 8
+# define STM32_GPIOI_MODER (STM32_GPIOI_BASE+STM32_GPIO_MODER_OFFSET)
+# define STM32_GPIOI_OTYPER (STM32_GPIOI_BASE+STM32_GPIO_OTYPER_OFFSET)
+# define STM32_GPIOI_OSPEED (STM32_GPIOI_BASE+STM32_GPIO_OSPEED_OFFSET)
+# define STM32_GPIOI_PUPDR (STM32_GPIOI_BASE+STM32_GPIO_PUPDR_OFFSET)
+# define STM32_GPIOI_IDR (STM32_GPIOI_BASE+STM32_GPIO_IDR_OFFSET)
+# define STM32_GPIOI_ODR (STM32_GPIOI_BASE+STM32_GPIO_ODR_OFFSET)
+# define STM32_GPIOI_BSRR (STM32_GPIOI_BASE+STM32_GPIO_BSRR_OFFSET)
+# define STM32_GPIOI_LCKR (STM32_GPIOI_BASE+STM32_GPIO_LCKR_OFFSET)
+# define STM32_GPIOI_AFRL (STM32_GPIOI_BASE+STM32_GPIO_AFRL_OFFSET)
+# define STM32_GPIOI_ARFH (STM32_GPIOI_BASE+STM32_GPIO_ARFH_OFFSET)
+#endif
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* GPIO port mode register */
+
+#define GPIO_MODER_INPUT (0) /* Input */
+#define GPIO_MODER_OUTPUT (1) /* General purpose output mode */
+#define GPIO_MODER_ALT (2) /* Alternate mode */
+#define GPIO_MODER_ANALOG (3) /* Analog mode */
+
+#define GPIO_MODER_SHIFT(n) ((n) << 1)
+#define GPIO_MODER_MASK(n) (3 << GPIO_MODER_SHIFT(n))
+
+#define GPIO_MODER0_SHIFT (0)
+#define GPIO_MODER0_MASK (3 << GPIO_MODER0_SHIFT)
+#define GPIO_MODER1_SHIFT (2)
+#define GPIO_MODER1_MASK (3 << GPIO_MODER1_SHIFT)
+#define GPIO_MODER2_SHIFT (4)
+#define GPIO_MODER2_MASK (3 << GPIO_MODER2_SHIFT)
+#define GPIO_MODER3_SHIFT (6)
+#define GPIO_MODER3_MASK (3 << GPIO_MODER3_SHIFT)
+#define GPIO_MODER4_SHIFT (8)
+#define GPIO_MODER4_MASK (3 << GPIO_MODER4_SHIFT)
+#define GPIO_MODER5_SHIFT (10)
+#define GPIO_MODER5_MASK (3 << GPIO_MODER5_SHIFT)
+#define GPIO_MODER6_SHIFT (12)
+#define GPIO_MODER6_MASK (3 << GPIO_MODER6_SHIFT)
+#define GPIO_MODER7_SHIFT (14)
+#define GPIO_MODER7_MASK (3 << GPIO_MODER7_SHIFT)
+#define GPIO_MODER8_SHIFT (16)
+#define GPIO_MODER8_MASK (3 << GPIO_MODER8_SHIFT)
+#define GPIO_MODER9_SHIFT (18)
+#define GPIO_MODER9_MASK (3 << GPIO_MODER9_SHIFT)
+#define GPIO_MODER10_SHIFT (20)
+#define GPIO_MODER10_MASK (3 << GPIO_MODER10_SHIFT)
+#define GPIO_MODER11_SHIFT (22)
+#define GPIO_MODER11_MASK (3 << GPIO_MODER11_SHIFT)
+#define GPIO_MODER12_SHIFT (24)
+#define GPIO_MODER12_MASK (3 << GPIO_MODER12_SHIFT)
+#define GPIO_MODER13_SHIFT (26)
+#define GPIO_MODER13_MASK (3 << GPIO_MODER13_SHIFT)
+#define GPIO_MODER14_SHIFT (28)
+#define GPIO_MODER14_MASK (3 << GPIO_MODER14_SHIFT)
+#define GPIO_MODER15_SHIFT (30)
+#define GPIO_MODER15_MASK (3 << GPIO_MODER15_SHIFT)
+
+/* GPIO port output type register */
+
+#define GPIO_OTYPER_OD(n) (1 << (n)) /* 1=Output open-drain */
+#define GPIO_OTYPER_PP(n) (0) /* 0=Ouput push-pull */
+
+/* GPIO port output speed register */
+
+#define GPIO_OSPEED_2MHz (0) /* 2 MHz Low speed */
+#define GPIO_OSPEED_25MHz (1) /* 25 MHz Medium speed */
+#define GPIO_OSPEED_50MHz (2) /* 50 MHz Fast speed */
+#define GPIO_OSPEED_100MHz (3) /* 100 MHz High speed on 30 pF (80 MHz Output max speed on 15 pF) */
+
+#define GPIO_OSPEED_SHIFT(n) ((n) << 1)
+#define GPIO_OSPEED_MASK(n) (3 << GPIO_OSPEED_SHIFT(n))
+
+#define GPIO_OSPEED0_SHIFT (0)
+#define GPIO_OSPEED0_MASK (3 << GPIO_OSPEED0_SHIFT)
+#define GPIO_OSPEED1_SHIFT (2)
+#define GPIO_OSPEED1_MASK (3 << GPIO_OSPEED1_SHIFT)
+#define GPIO_OSPEED2_SHIFT (4)
+#define GPIO_OSPEED2_MASK (3 << GPIO_OSPEED2_SHIFT)
+#define GPIO_OSPEED3_SHIFT (6)
+#define GPIO_OSPEED3_MASK (3 << GPIO_OSPEED3_SHIFT)
+#define GPIO_OSPEED4_SHIFT (8)
+#define GPIO_OSPEED4_MASK (3 << GPIO_OSPEED4_SHIFT)
+#define GPIO_OSPEED5_SHIFT (10)
+#define GPIO_OSPEED5_MASK (3 << GPIO_OSPEED5_SHIFT)
+#define GPIO_OSPEED6_SHIFT (12)
+#define GPIO_OSPEED6_MASK (3 << GPIO_OSPEED6_SHIFT)
+#define GPIO_OSPEED7_SHIFT (14)
+#define GPIO_OSPEED7_MASK (3 << GPIO_OSPEED7_SHIFT)
+#define GPIO_OSPEED8_SHIFT (16)
+#define GPIO_OSPEED8_MASK (3 << GPIO_OSPEED8_SHIFT)
+#define GPIO_OSPEED9_SHIFT (18)
+#define GPIO_OSPEED9_MASK (3 << GPIO_OSPEED9_SHIFT)
+#define GPIO_OSPEED10_SHIFT (20)
+#define GPIO_OSPEED10_MASK (3 << GPIO_OSPEED10_SHIFT)
+#define GPIO_OSPEED11_SHIFT (22)
+#define GPIO_OSPEED11_MASK (3 << GPIO_OSPEED11_SHIFT)
+#define GPIO_OSPEED12_SHIFT (24)
+#define GPIO_OSPEED12_MASK (3 << GPIO_OSPEED12_SHIFT)
+#define GPIO_OSPEED13_SHIFT (26)
+#define GPIO_OSPEED13_MASK (3 << GPIO_OSPEED13_SHIFT)
+#define GPIO_OSPEED14_SHIFT (28)
+#define GPIO_OSPEED14_MASK (3 << GPIO_OSPEED14_SHIFT)
+#define GPIO_OSPEED15_SHIFT (30)
+#define GPIO_OSPEED15_MASK (3 << GPIO_OSPEED15_SHIFT)
+
+/* GPIO port pull-up/pull-down register */
+
+#define GPIO_PUPDR_NONE (0) /* No pull-up, pull-down */
+#define GPIO_PUPDR_PULLUP (1) /* Pull-up */
+#define GPIO_PUPDR_PULLDOWN (2) /* Pull-down */
+
+#define GPIO_PUPDR_SHIFT(n) ((n) << 1)
+#define GPIO_PUPDR_MASK(n) (3 << GPIO_PUPDR_SHIFT(n))
+
+#define GPIO_PUPDR0_SHIFT (0)
+#define GPIO_PUPDR0_MASK (3 << GPIO_PUPDR0_SHIFT)
+#define GPIO_PUPDR1_SHIFT (2)
+#define GPIO_PUPDR1_MASK (3 << GPIO_PUPDR1_SHIFT)
+#define GPIO_PUPDR2_SHIFT (4)
+#define GPIO_PUPDR2_MASK (3 << GPIO_PUPDR2_SHIFT)
+#define GPIO_PUPDR3_SHIFT (6)
+#define GPIO_PUPDR3_MASK (3 << GPIO_PUPDR3_SHIFT)
+#define GPIO_PUPDR4_SHIFT (8)
+#define GPIO_PUPDR4_MASK (3 << GPIO_PUPDR4_SHIFT)
+#define GPIO_PUPDR5_SHIFT (10)
+#define GPIO_PUPDR5_MASK (3 << GPIO_PUPDR5_SHIFT)
+#define GPIO_PUPDR6_SHIFT (12)
+#define GPIO_PUPDR6_MASK (3 << GPIO_PUPDR6_SHIFT)
+#define GPIO_PUPDR7_SHIFT (14)
+#define GPIO_PUPDR7_MASK (3 << GPIO_PUPDR7_SHIFT)
+#define GPIO_PUPDR8_SHIFT (16)
+#define GPIO_PUPDR8_MASK (3 << GPIO_PUPDR8_SHIFT)
+#define GPIO_PUPDR9_SHIFT (18)
+#define GPIO_PUPDR9_MASK (3 << GPIO_PUPDR9_SHIFT)
+#define GPIO_PUPDR10_SHIFT (20)
+#define GPIO_PUPDR10_MASK (3 << GPIO_PUPDR10_SHIFT)
+#define GPIO_PUPDR11_SHIFT (22)
+#define GPIO_PUPDR11_MASK (3 << GPIO_PUPDR11_SHIFT)
+#define GPIO_PUPDR12_SHIFT (24)
+#define GPIO_PUPDR12_MASK (3 << GPIO_PUPDR12_SHIFT)
+#define GPIO_PUPDR13_SHIFT (26)
+#define GPIO_PUPDR13_MASK (3 << GPIO_PUPDR13_SHIFT)
+#define GPIO_PUPDR14_SHIFT (28)
+#define GPIO_PUPDR14_MASK (3 << GPIO_PUPDR14_SHIFT)
+#define GPIO_PUPDR15_SHIFT (30)
+#define GPIO_PUPDR15_MASK (3 << GPIO_PUPDR15_SHIFT)
+
+/* GPIO port input data register */
+
+#define GPIO_IDR(n) (1 << (n))
+
+/* GPIO port output data register */
+
+#define GPIO_ODR(n) (1 << (n))
+
+/* GPIO port bit set/reset register */
+
+#define GPIO_BSRR_SET(n) (1 << (n))
+#define GPIO_BSRR_RESET(n) (1 << ((n)+16))
+
+/* GPIO port configuration lock register */
+
+#define GPIO_LCKR(n) (1 << (n))
+#define GPIO_LCKK (1 << 16) /* Lock key */
+
+/* GPIO alternate function low/high register */
+
+#define GPIO_AFR_SHIFT(n) ((n) << 2)
+#define GPIO_AFR_MASK(n) (15 << GPIO_AFR_SHIFT(n))
+
+#define GPIO_AFRL0_SHIFT (0)
+#define GPIO_AFRL0_MASK (15 << GPIO_AFRL0_SHIFT)
+#define GPIO_AFRL1_SHIFT (4)
+#define GPIO_AFRL1_MASK (15 << GPIO_AFRL1_SHIFT)
+#define GPIO_AFRL2_SHIFT (8)
+#define GPIO_AFRL2_MASK (15 << GPIO_AFRL2_SHIFT)
+#define GPIO_AFRL3_SHIFT (12)
+#define GPIO_AFRL3_MASK (15 << GPIO_AFRL3_SHIFT)
+#define GPIO_AFRL4_SHIFT (16)
+#define GPIO_AFRL4_MASK (15 << GPIO_AFRL4_SHIFT)
+#define GPIO_AFRL5_SHIFT (20)
+#define GPIO_AFRL5_MASK (15 << GPIO_AFRL5_SHIFT)
+#define GPIO_AFRL6_SHIFT (24)
+#define GPIO_AFRL6_MASK (15 << GPIO_AFRL6_SHIFT)
+#define GPIO_AFRL7_SHIFT (28)
+#define GPIO_AFRL7_MASK (15 << GPIO_AFRL7_SHIFT)
+
+#define GPIO_AFRH8_SHIFT (0)
+#define GPIO_AFRH8_MASK (15 << GPIO_AFRH8_SHIFT)
+#define GPIO_AFRH9_SHIFT (4)
+#define GPIO_AFRH9_MASK (15 << GPIO_AFRH9_SHIFT)
+#define GPIO_AFRH10_SHIFT (8)
+#define GPIO_AFRH10_MASK (15 << GPIO_AFRH10_SHIFT)
+#define GPIO_AFRH11_SHIFT (12)
+#define GPIO_AFRH11_MASK (15 << GPIO_AFRH11_SHIFT)
+#define GPIO_AFRH12_SHIFT (16)
+#define GPIO_AFRH12_MASK (15 << GPIO_AFRH12_SHIFT)
+#define GPIO_AFRH13_SHIFT (20)
+#define GPIO_AFRH13_MASK (15 << GPIO_AFRH13_SHIFT)
+#define GPIO_AFRH14_SHIFT (24)
+#define GPIO_AFRH14_MASK (15 << GPIO_AFRH14_SHIFT)
+#define GPIO_AFRH15_SHIFT (28)
+#define GPIO_AFRH15_MASK (15 << GPIO_AFRH15_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_GPIO_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_memorymap.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_memorymap.h
new file mode 100644
index 000000000..c7f7ff2ec
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_memorymap.h
@@ -0,0 +1,197 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f40xxx_memorymap.h
+ *
+ * Copyright (C) 2011-2012 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_STM32_CHIP_STM32F40XXX_MEMORYMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_MEMORYMAP_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* STM32F40XXX Address Blocks *******************************************************/
+
+#define STM32_CODE_BASE 0x00000000 /* 0x00000000-0x1fffffff: 512Mb code block */
+#define STM32_SRAM_BASE 0x20000000 /* 0x20000000-0x3fffffff: 512Mb sram block */
+#define STM32_PERIPH_BASE 0x40000000 /* 0x40000000-0x5fffffff: 512Mb peripheral block */
+#define STM32_FSMC_BASE12 0x60000000 /* 0x60000000-0x7fffffff: 512Mb FSMC bank1&2 block */
+#define STM32_FSMC_BASE34 0x80000000 /* 0x80000000-0x8fffffff: 512Mb FSMC bank3&4 block */
+#define STM32_FSMC_BASE 0xa0000000 /* 0xa0000000-0xbfffffff: 512Mb FSMC register block */
+ /* 0xc0000000-0xdfffffff: 512Mb (not used) */
+#define STM32_CORTEX_BASE 0xe0000000 /* 0xe0000000-0xffffffff: 512Mb Cortex-M4 block */
+
+/* Code Base Addresses **************************************************************/
+
+#define STM32_BOOT_BASE 0x00000000 /* 0x00000000-0x000fffff: Aliased boot memory */
+ /* 0x00100000-0x07ffffff: Reserved */
+#define STM32_FLASH_BASE 0x08000000 /* 0x08000000-0x080fffff: FLASH memory */
+ /* 0x08100000-0x0fffffff: Reserved */
+#define STM32_CCMRAM_BASE 0x10000000 /* 0x10000000-0x1000ffff: 64Kb CCM data RAM */
+ /* 0x10010000-0x1ffeffff: Reserved */
+#define STM32_SYSMEM_BASE 0x1fff0000 /* 0x1fff0000-0x1fff7a0f: System memory */
+ /* 0x1fff7a10-0x1fff7fff: Reserved */
+#define STM32_OPTION_BASE 0x1fffc000 /* 0x1fffc000-0x1fffc007: Option bytes */
+ /* 0x1fffc008-0x1fffffff: Reserved */
+
+/* SRAM Base Addresses **************************************************************/
+
+ /* 0x20000000-0x2001bfff: 112Kb aliased by bit-banding */
+ /* 0x2001c000-0x2001ffff: 16Kb aliased by bit-banding */
+#define STM32_SRAMBB_BASE 0x22000000 /* 0x22000000- : SRAM bit-band region */
+
+/* Peripheral Base Addresses ********************************************************/
+
+#define STM32_APB1_BASE 0x40000000 /* 0x40000000-0x400023ff: APB1 */
+ /* 0x40002400-0x400027ff: Reserved */
+ /* 0x40002800-0x400077ff: APB1 */
+ /* 0x40007800-0x4000ffff: Reserved */
+#define STM32_APB2_BASE 0x40010000 /* 0x40010000-0x400023ff: APB2 */
+ /* 0x40013400-0x400137ff: Reserved */
+ /* 0x40013800-0x40013bff: SYSCFG */
+#define STM32_EXTI_BASE 0x40013c00 /* 0x40013c00-0x40013fff: EXTI */
+ /* 0x40014000-0x40014bff: APB2 */
+ /* 0x40014c00-0x4001ffff: Reserved */
+#define STM32_AHB1_BASE 0x40020000 /* 0x40020000-0x400223ff: APB1 */
+ /* 0x40022400-0x40022fff: Reserved */
+ /* 0x40023000-0x400233ff: CRC */
+ /* 0x40023400-0x400237ff: Reserved */
+ /* 0x40023800-0x40023bff: Reset and Clock control RCC */
+ /* 0x40023c00-0x400293ff: AHB1 (?) */
+ /* 0x40029400-0x4fffffff: Reserved (?) */
+#define STM32_AHB2_BASE 0x50000000 /* 0x50000000-0x5003ffff: AHB2 */
+ /* 0x50040000-0x5004ffff: Reserved */
+ /* 0x50050000-0x500503ff: AHB2 */
+ /* 0x50050400-0x500607ff: Reserved */
+ /* 0x50060800-0x50060bff: AHB2 */
+ /* 0x50060c00-0x5fffffff: Reserved */
+
+/* FSMC Base Addresses **************************************************************/
+
+#define STM32_AHB3_BASE 0x60000000 /* 0x60000000-0xa0000fff: AHB3 */
+
+/* APB1 Base Addresses **************************************************************/
+
+#define STM32_TIM2_BASE 0x40000000 /* 0x40000000-0x400003ff: TIM2 timer */
+#define STM32_TIM3_BASE 0x40000400 /* 0x40000400-0x400007ff: TIM3 timer */
+#define STM32_TIM4_BASE 0x40000800 /* 0x40000800-0x40000bff: TIM4 timer */
+#define STM32_TIM5_BASE 0x40000c00 /* 0x40000c00-0x40000fff: TIM5 timer */
+#define STM32_TIM6_BASE 0x40001000 /* 0x40001000-0x400013ff: TIM6 timer */
+#define STM32_TIM7_BASE 0x40001400 /* 0x40001400-0x400017ff: TIM7 timer */
+#define STM32_TIM12_BASE 0x40001800 /* 0x40001800-0x40001bff: TIM12 timer */
+#define STM32_TIM13_BASE 0x40001c00 /* 0x40001c00-0x40001fff: TIM13 timer */
+#define STM32_TIM14_BASE 0x40002000 /* 0x40002000-0x400023ff: TIM14 timer */
+#define STM32_RTC_BASE 0x40002800 /* 0x40002800-0x40002bff: RTC & BKP registers */
+#define STM32_BKP_BASE 0x40002850
+#define STM32_WWDG_BASE 0x40002c00 /* 0x40002c00-0x40002fff: Window watchdog (WWDG) */
+#define STM32_IWDG_BASE 0x40003000 /* 0x40003000-0x400033ff: Independent watchdog (IWDG) */
+#define STM32_I2S2EXT_BASE 0x40003400 /* 0x40003400-0x400037ff: I2S2ext */
+#define STM32_SPI2_BASE 0x40003800 /* 0x40003800-0x40003bff: SPI2/I2S2 */
+#define STM32_I2S2_BASE 0x40003800
+#define STM32_SPI3_BASE 0x40003c00 /* 0x40003c00-0x40003fff: SPI3/I2S3 */
+#define STM32_I2S3_BASE 0x40003c00
+#define STM32_I2S3EXT_BASE 0x40004000 /* 0x40003400-0x400043ff: I2S3ext */
+#define STM32_USART2_BASE 0x40004400 /* 0x40004400-0x400047ff: USART2 */
+#define STM32_USART3_BASE 0x40004800 /* 0x40004800-0x40004bff: USART3 */
+#define STM32_UART4_BASE 0x40004c00 /* 0x40004c00-0x40004fff: UART4 */
+#define STM32_UART5_BASE 0x40005000 /* 0x40005000-0x400053ff: UART5 */
+#define STM32_I2C1_BASE 0x40005400 /* 0x40005400-0x400057ff: I2C1 */
+#define STM32_I2C2_BASE 0x40005800 /* 0x40005800-0x40005Bff: I2C2 */
+#define STM32_I2C3_BASE 0x40005c00 /* 0x40005c00-0x40005fff: I2C3 */
+#define STM32_CAN1_BASE 0x40006400 /* 0x40006400-0x400067ff: bxCAN1 */
+#define STM32_CAN2_BASE 0x40006800 /* 0x40006800-0x40006bff: bxCAN2 */
+#define STM32_PWR_BASE 0x40007000 /* 0x40007000-0x400073ff: Power control PWR */
+#define STM32_DAC_BASE 0x40007400 /* 0x40007400-0x400077ff: DAC */
+
+/* APB2 Base Addresses **************************************************************/
+
+#define STM32_TIM1_BASE 0x40010000 /* 0x40010000-0x400103ff: TIM1 timer */
+#define STM32_TIM8_BASE 0x40010400 /* 0x40010400-0x400107ff: TIM8 timer */
+#define STM32_USART1_BASE 0x40011000 /* 0x40011000-0x400113ff: USART1 */
+#define STM32_USART6_BASE 0x40011400 /* 0x40011400-0x400117ff: USART6 */
+#define STM32_ADC_BASE 0x40012000 /* 0x40012000-0x400123ff: ADC1-3 */
+# define STM32_ADC1_BASE 0x40012000 /* ADC1 */
+# define STM32_ADC2_BASE 0x40012100 /* ADC2 */
+# define STM32_ADC3_BASE 0x40012200 /* ADC3 */
+# define STM32_ADCCMN_BASE 0x40012300 /* Common */
+#define STM32_SDIO_BASE 0x40012c00 /* 0x40012c00-0x40012fff: SDIO */
+#define STM32_SPI1_BASE 0x40013000 /* 0x40013000-0x400133ff: SPI1 */
+#define STM32_SYSCFG_BASE 0x40013800 /* 0x40013800-0x40013bff: SYSCFG */
+#define STM32_EXTI_BASE 0x40013c00 /* 0x40013c00-0x40013fff: EXTI */
+#define STM32_TIM9_BASE 0x40014000 /* 0x40014000-0x400143ff: TIM9 timer */
+#define STM32_TIM10_BASE 0x40014400 /* 0x40014400-0x400147ff: TIM10 timer */
+#define STM32_TIM11_BASE 0x40014800 /* 0x40014800-0x40014bff: TIM11 timer */
+
+/* AHB1 Base Addresses **************************************************************/
+
+#define STM32_GPIOA_BASE 0x40020000 /* 0x40020000-0x400203ff: GPIO Port A */
+#define STM32_GPIOB_BASE 0x40020400 /* 0x40020400-0x400207ff: GPIO Port B */
+#define STM32_GPIOC_BASE 0x40020800 /* 0x40020800-0x40020bff: GPIO Port C */
+#define STM32_GPIOD_BASE 0X40020C00 /* 0x40020c00-0x40020fff: GPIO Port D */
+#define STM32_GPIOE_BASE 0x40021000 /* 0x40021000-0x400213ff: GPIO Port E */
+#define STM32_GPIOF_BASE 0x40021400 /* 0x40021400-0x400217ff: GPIO Port F */
+#define STM32_GPIOG_BASE 0x40021800 /* 0x40021800-0x40021bff: GPIO Port G */
+#define STM32_GPIOH_BASE 0x40021C00 /* 0x40021C00-0x40021fff: GPIO Port H */
+#define STM32_GPIOI_BASE 0x40022000 /* 0x40022000-0x400223ff: GPIO Port I */
+#define STM32_CRC_BASE 0x40023000 /* 0x40023000-0x400233ff: CRC */
+#define STM32_RCC_BASE 0x40023800 /* 0x40023800-0x40023bff: Reset and Clock control RCC */
+#define STM32_FLASHIF_BASE 0x40023c00 /* 0x40023c00-0x40023fff: Flash memory interface */
+#define STM32_BKPSRAM_BASE 0x40024000 /* 0x40024000-0x40024fff: Backup SRAM (BKPSRAM) */
+#define STM32_DMA1_BASE 0x40026000 /* 0x40026000-0x400263ff: DMA1 */
+#define STM32_DMA2_BASE 0x40026400 /* 0x40026400-0x400267ff: DMA2 */
+#define STM32_ETHERNET_BASE 0x40028000 /* 0x40028000-0x400283ff: Ethernet MAC */
+ /* 0x40028400-0x400287ff: Ethernet MAC */
+ /* 0x40028800-0x40028bff: Ethernet MAC */
+ /* 0x40028c00-0x40028fff: Ethernet MAC */
+ /* 0x40029000-0x400293ff: Ethernet MAC */
+#define STM32_OTGHS_BASE 0x40040000 /* 0x40040000-0x4007ffff: USB OTG HS */
+#define STM32_PERIPHBB_BASE 0x42000000 /* Peripheral bit-band region */
+
+/* AHB2 Base Addresses **************************************************************/
+
+#define STM32_OTGFS_BASE 0x50000000 /* 0x50000000-0x5003ffff: USB OTG FS */
+#define STM32_DCMI_BASE 0x50050000 /* 0x50050000-0x500503ff: DCMI */
+#define STM32_CRYP_BASE 0x50060000 /* 0x50060000-0x500603ff: CRYP */
+#define STM32_HASH_BASE 0x50060400 /* 0x50060400-0x500607ff: HASH */
+#define STM32_RNG_BASE 0x50060800 /* 0x50060800-0x50060bff: RNG */
+
+/* Cortex-M4 Base Addresses *********************************************************/
+/* Other registers -- see armv7-m/nvic.h for standard Cortex-M3 registers in this
+ * address range
+ */
+
+#define STM32_SCS_BASE 0xe000e000
+#define STM32_DEBUGMCU_BASE 0xe0042000
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_MEMORYMAP_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h
new file mode 100644
index 000000000..a588b56a2
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h
@@ -0,0 +1,695 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h
+ *
+ * Copyright (C) 2011-2012 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_STM32_CHIP_STM32F40XXX_PINMAP_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_PINMAP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "stm32_gpio.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Alternate Pin Functions. All members of the STM32F40xxx family share the same
+ * pin multiplexing (although they may differ in the pins physically available).
+ *
+ * Alternative pin selections are provided with a numeric suffix like _1, _2, etc.
+ * Drivers, however, will use the pin selection without the numeric suffix.
+ * Additional definitions are required in the board.h file. For example, if
+ * CAN1_RX connects vis PA11 on some board, then the following definitions should
+ * appear inthe board.h header file for that board:
+ *
+ * #define GPIO_CAN1_RX GPIO_CAN1_RX_1
+ *
+ * The driver will then automatically configre PA11 as the CAN1 RX pin.
+ */
+
+/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
+ * Additional effort is required to select specific GPIO options such as frequency,
+ * open-drain/push-pull, and pull-up/down! Just the basics are defined for most
+ * pins in this file.
+ */
+
+/* ADC */
+
+#define GPIO_ADC1_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC1_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC1_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC1_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC1_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_ADC1_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_ADC1_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_ADC1_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ADC1_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ADC1_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_ADC1_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC1_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC1_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC1_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC1_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ADC1_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5)
+
+#define GPIO_ADC2_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC2_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC2_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC2_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC2_IN4 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_ADC2_IN5 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_ADC2_IN6 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_ADC2_IN7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ADC2_IN8 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ADC2_IN9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_ADC2_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC2_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC2_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC2_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC2_IN14 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ADC2_IN15 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5)
+
+#define GPIO_ADC3_IN0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ADC3_IN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ADC3_IN2 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ADC3_IN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ADC3_IN4 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN6)
+#define GPIO_ADC3_IN5 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN7)
+#define GPIO_ADC3_IN6 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN8)
+#define GPIO_ADC3_IN7 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN9)
+#define GPIO_ADC3_IN9 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN3)
+#define GPIO_ADC3_IN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0)
+#define GPIO_ADC3_IN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ADC3_IN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ADC3_IN13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ADC3_IN14 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN4)
+#define GPIO_ADC3_IN15 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN5)
+
+/* CAN */
+
+#define GPIO_CAN1_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_CAN1_RX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_CAN1_RX_3 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_CAN1_RX_4 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN9)
+#define GPIO_CAN1_TX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_CAN1_TX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_CAN1_TX_3 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_CAN1_TX_4 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN13)
+
+#define GPIO_CAN2_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_CAN2_RX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_CAN2_TX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_CAN2_TX_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6)
+
+/* DAC -" Once the DAC channelx is enabled, the corresponding GPIO pin
+ * (PA4 or PA5) is automatically connected to the analog converter output
+ * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin
+ * should first be configured to analog (AIN)".
+ */
+
+#define GPIO_DAC1_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_DAC2_OUT (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5)
+
+/* Digital Camera Interface (DCMI) */
+
+#define GPIO_DCMI_D0_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_DCMI_D0_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_DCMI_D0_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN9)
+#define GPIO_DCMI_D1_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_DCMI_D1_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_DCMI_D1_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN10)
+#define GPIO_DCMI_D2_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_DCMI_D2_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN0)
+#define GPIO_DCMI_D2_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN11)
+#define GPIO_DCMI_D3_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_DCMI_D3_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN1)
+#define GPIO_DCMI_D3_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN12)
+#define GPIO_DCMI_D4_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_DCMI_D4_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_DCMI_D4_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN14)
+#define GPIO_DCMI_D5_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_DCMI_D5_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN4)
+#define GPIO_DCMI_D6_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_DCMI_D6_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_DCMI_D6_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN6)
+#define GPIO_DCMI_D7_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_DCMI_D7_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_DCMI_D7_3 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN7)
+#define GPIO_DCMI_D8_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN10)
+#define GPIO_DCMI_D8_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN1)
+#define GPIO_DCMI_D9_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_DCMI_D9_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN2)
+#define GPIO_DCMI_D10_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_DCMI_D10_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN3)
+#define GPIO_DCMI_D11_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTD|GPIO_PIN2)
+#define GPIO_DCMI_D11_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN15)
+#define GPIO_DCMI_D12 (GPIO_ALT|GPIO_AF13|GPIO_PORTF|GPIO_PIN11)
+#define GPIO_DCMI_D13_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTG|GPIO_PIN15)
+#define GPIO_DCMI_D13_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN0)
+#define GPIO_DCMI_HSYNC_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_DCMI_HSYNC_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTH|GPIO_PIN8)
+#define GPIO_DCMI_PIXCK (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_DCMI_VSYNC_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_DCMI_VSYNC_2 (GPIO_ALT|GPIO_AF13|GPIO_PORTI|GPIO_PIN5)
+
+/* Clocks outputs */
+
+#define GPIO_MCO1 (GPIO_ALT|GPIO_AF0|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_MCO2 (GPIO_ALT|GPIO_AF0|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
+
+/* Ethernet MAC */
+
+#define GPIO_ETH_MDC (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN1)
+#define GPIO_ETH_MDIO (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_ETH_MII_COL_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_ETH_MII_COL_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN3)
+#define GPIO_ETH_MII_CRS_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_ETH_MII_CRS_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN2)
+#define GPIO_ETH_MII_RXD0 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ETH_MII_RXD1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN5)
+#define GPIO_ETH_MII_RXD2_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_ETH_MII_RXD2_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6)
+#define GPIO_ETH_MII_RXD3_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_ETH_MII_RXD3_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN7)
+#define GPIO_ETH_MII_RX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ETH_MII_RX_DV (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_ETH_MII_RX_ER_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_ETH_MII_RX_ER_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN10)
+#define GPIO_ETH_MII_TXD0_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_ETH_MII_TXD0_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_ETH_MII_TXD1_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_ETH_MII_TXD1_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14)
+#define GPIO_ETH_MII_TXD2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_ETH_MII_TXD3_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_ETH_MII_TXD3_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_ETH_MII_TX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ETH_MII_TX_EN_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_ETH_MII_TX_EN_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11)
+#define GPIO_ETH_PPS_OUT_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_ETH_PPS_OUT_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN8)
+#define GPIO_ETH_RMII_CRS_DV (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULLGPIO_PORTA|GPIO_PIN7)
+#define GPIO_ETH_RMII_REF_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_ETH_RMII_RXD0 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4)
+#define GPIO_ETH_RMII_RXD1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN5)
+#define GPIO_ETH_RMII_TXD0_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_ETH_RMII_TXD0_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_ETH_RMII_TXD1_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_ETH_RMII_TXD1_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14)
+#define GPIO_ETH_RMII_TX_CLK (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_ETH_RMII_TX_EN_1 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_ETH_RMII_TX_EN_2 (GPIO_ALT|GPIO_AF11|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11)
+
+/* Flexible Static Memory Controller (FSMC) */
+
+#define GPIO_FSMC_A0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN0)
+#define GPIO_FSMC_A1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN1)
+#define GPIO_FSMC_A2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN2)
+#define GPIO_FSMC_A3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN3)
+#define GPIO_FSMC_A4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN4)
+#define GPIO_FSMC_A5 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN5)
+#define GPIO_FSMC_A6 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN12)
+#define GPIO_FSMC_A7 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN13)
+#define GPIO_FSMC_A8 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN14)
+#define GPIO_FSMC_A9 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN15)
+#define GPIO_FSMC_A10 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN0)
+#define GPIO_FSMC_A11 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN1)
+#define GPIO_FSMC_A12 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN2)
+#define GPIO_FSMC_A13 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN3)
+#define GPIO_FSMC_A14 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN4)
+#define GPIO_FSMC_A15 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN5)
+#define GPIO_FSMC_A16 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN11)
+#define GPIO_FSMC_A17 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_FSMC_A18 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN13)
+#define GPIO_FSMC_A19 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_FSMC_A20 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_FSMC_A21 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_FSMC_A22 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_FSMC_A23 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_FSMC_A24 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_FSMC_A25 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN14)
+#define GPIO_FSMC_NBL1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN1)
+#define GPIO_FSMC_CD (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN9)
+#define GPIO_FSMC_CLK (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN3)
+#define GPIO_FSMC_D0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_FSMC_D1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_FSMC_D2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN0)
+#define GPIO_FSMC_D3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN1)
+#define GPIO_FSMC_D4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN7)
+#define GPIO_FSMC_D5 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_FSMC_D6 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_FSMC_D7 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_FSMC_D8 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_FSMC_D9 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_FSMC_D10 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_FSMC_D11 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_FSMC_D12 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_FSMC_D13 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN8)
+#define GPIO_FSMC_D14 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_FSMC_D15 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN10)
+#define GPIO_FSMC_INT2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN6)
+#define GPIO_FSMC_INT3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN7)
+#define GPIO_FSMC_INTR (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN10)
+#define GPIO_FSMC_NBL0 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN0)
+#define GPIO_FSMC_NCE2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN7)
+#define GPIO_FSMC_NCE3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN9)
+#define GPIO_FSMC_NCE4_1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN10)
+#define GPIO_FSMC_NCE4_2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN11)
+#define GPIO_FSMC_NE1 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN7)
+#define GPIO_FSMC_NE2 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN9)
+#define GPIO_FSMC_NE3 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN10)
+#define GPIO_FSMC_NE4 (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTG|GPIO_PIN12)
+#define GPIO_FSMC_NIORD (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN6)
+#define GPIO_FSMC_NIOWR (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN8)
+#define GPIO_FSMC_NL (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_FSMC_NOE (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_FSMC_NREG (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTF|GPIO_PIN7)
+#define GPIO_FSMC_NWAIT (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_FSMC_NWE (GPIO_ALT|GPIO_AF12|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN5)
+
+/* I2C */
+
+#define GPIO_I2C1_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_I2C1_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_I2C1_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_I2C1_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_I2C1_SMBA (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5)
+
+#define GPIO_I2C2_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2C2_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTF|GPIO_PIN1)
+#define GPIO_I2C2_SCL_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN4)
+#define GPIO_I2C2_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_I2C2_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTF|GPIO_PIN0)
+#define GPIO_I2C2_SDA_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN5)
+#define GPIO_I2C2_SMBA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_I2C2_SMBA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN2)
+#define GPIO_I2C2_SMBA_3 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6)
+
+#define GPIO_I2C3_SCL_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_I2C3_SCL_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN7)
+#define GPIO_I2C3_SDA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_I2C3_SDA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_OPENDRAIN|GPIO_PORTH|GPIO_PIN8)
+#define GPIO_I2C3_SMBA_1 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_I2C3_SMBA_2 (GPIO_ALT|GPIO_AF4|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9)
+
+/* I2S */
+
+#define GPIO_I2S2_CK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_I2S2_CK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_I2S2_CK_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN1)
+#define GPIO_I2S2_MCK (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_I2S2_SD_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_I2S2_SD_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_I2S2_SD_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN3)
+#define GPIO_I2S2_WS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_I2S2_WS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_I2S2_WS_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_I2S2_WS_4 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN0)
+
+#define GPIO_I2S2EXT_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_I2S2EXT_SD_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_I2S2EXT_SD_3 (GPIO_ALT|GPIO_AF6|GPIO_PORTI|GPIO_PIN2)
+
+#define GPIO_I2S3_CK_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_I2S3_CK_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN10)
+#define GPIO_I2S3_MCK (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_I2S3_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_I2S3_SD_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_I2S3_WS_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_I2S3_WS_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN15)
+
+#define GPIO_I2S3EXT_SD_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_I2S3EXT_SD_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN4)
+
+#define GPIO_I2S_CKIN (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN9)
+
+/* JTAG */
+
+#define GPIO_JTCK_SWCLK (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN14)
+#define GPIO_JTDI (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_JTDO (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_JTMS_SWDIO (GPIO_ALT|GPIO_AF0|GPIO_PORTA|GPIO_PIN13)
+#define GPIO_JTRST (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN4)
+
+/* OTG FS/HS */
+
+#define GPIO_OTGFS_DM (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_OTGFS_DP (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_OTGFS_ID (GPIO_ALT|GPIO_PULLUP|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_OTGFS_SCL (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_OTGFS_SDA (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_OTGFS_SOF (GPIO_ALT|GPIO_FLOAT|GPIO_AF10|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8)
+
+#define GPIO_OTGHS_DM (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_OTGHS_DP (GPIO_ALT|GPIO_AF12|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_OTGHS_ID (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_OTGHS_INTN_1 (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_OTGFS_INTN_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_OTGHS_SCL (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_OTGHS_SDA (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_OTGHS_SOF (GPIO_ALT|GPIO_AF12|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_OTGHS_ULPI_CK (GPIO_ALT|GPIO_AF10|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_OTGHS_ULPI_D0 (GPIO_ALT|GPIO_AF10|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_OTGHS_ULPI_D1 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_OTGHS_ULPI_D2 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_OTGHS_ULPI_D3 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_OTGHS_ULPI_D4 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_OTGHS_ULPI_D5 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_OTGHS_ULPI_D6 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_OTGHS_ULPI_D7 (GPIO_ALT|GPIO_AF10|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_OTGHS_ULPI_DIR_1 (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_OTGHS_ULPI_DIR_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTI|GPIO_PIN11)
+#define GPIO_OTGHS_ULPI_NXT_1 (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_OTGHS_ULPI_NXT_2 (GPIO_ALT|GPIO_AF10|GPIO_PORTH|GPIO_PIN4)
+#define GPIO_OTGHS_ULPI_STP (GPIO_ALT|GPIO_AF10|GPIO_PORTC|GPIO_PIN0)
+
+/* RTC */
+
+#define GPIO_RTC_50HZ (GPIO_ALT|GPIO_AF0|GPIO_PORTC|GPIO_PIN15)
+
+/* SDIO */
+
+#define GPIO_SDIO_CK (GPIO_ALT|GPIO_AF12|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_SDIO_CMD (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN2)
+#define GPIO_SDIO_D0 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_SDIO_D1 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_SDIO_D2 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10)
+#define GPIO_SDIO_D3 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_SDIO_D4 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_SDIO_D5 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_SDIO_D6 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_SDIO_D7 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
+
+/* SPI */
+
+#define GPIO_SPI1_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_SPI1_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN4)
+#define GPIO_SPI1_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_SPI1_MOSI_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_SPI1_NSS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_SPI1_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_SPI1_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_SPI1_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN3)
+
+#define GPIO_SPI2_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_SPI2_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN2)
+#define GPIO_SPI2_MISO_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN2)
+#define GPIO_SPI2_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_SPI2_MOSI_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTC|GPIO_PIN3)
+#define GPIO_SPI2_MOSI_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN3)
+#define GPIO_SPI2_NSS_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_SPI2_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_SPI2_NSS_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN0)
+#define GPIO_SPI2_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_SPI2_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_SPI2_SCK_3 (GPIO_ALT|GPIO_AF5|GPIO_PORTI|GPIO_PIN1)
+
+#define GPIO_SPI3_MISO_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN4)
+#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_SPI3_MOSI_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_SPI3_MOSI_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_SPI3_NSS_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_SPI3_NSS_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_SPI3_SCK_1 (GPIO_ALT|GPIO_AF6|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_SPI3_SCK_2 (GPIO_ALT|GPIO_AF6|GPIO_PORTC|GPIO_PIN10)
+
+/* Timers */
+
+#define GPIO_TIM1_BKIN_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM1_BKIN_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_TIM1_BKIN_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN15)
+#define GPIO_TIM1_CH1N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM1_CH1N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_TIM1_CH1N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN8)
+#define GPIO_TIM1_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_TIM1_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_TIM1_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_TIM1_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN9)
+#define GPIO_TIM1_CH2N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM1_CH2N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_TIM1_CH2N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN10)
+#define GPIO_TIM1_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_TIM1_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_TIM1_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_TIM1_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN11)
+#define GPIO_TIM1_CH3N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_TIM1_CH3N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_TIM1_CH3N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN12)
+#define GPIO_TIM1_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_TIM1_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_TIM1_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_TIM1_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN13)
+#define GPIO_TIM1_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_TIM1_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_TIM1_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_TIM1_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN14)
+#define GPIO_TIM1_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_TIM1_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN7)
+
+#define GPIO_TIM2_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM2_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_TIM2_CH1IN_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_TIM2_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM2_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_TIM2_CH1OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_TIM2_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM2_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_TIM2_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM2_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN3)
+#define GPIO_TIM2_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM2_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_TIM2_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM2_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_TIM2_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM2_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_TIM2_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM2_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_TIM2_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM2_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15)
+#define GPIO_TIM2_ETR_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5)
+
+#define GPIO_TIM3_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM3_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN4)
+#define GPIO_TIM3_CH1IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM3_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM3_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN4)
+#define GPIO_TIM3_CH1OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM3_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM3_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_TIM3_CH2IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM3_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM3_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5)
+#define GPIO_TIM3_CH2OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM3_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM3_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM3_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM3_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM3_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_TIM3_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM3_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_TIM3_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM3_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN2)
+
+#define GPIO_TIM4_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_TIM4_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_TIM4_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6)
+#define GPIO_TIM4_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_TIM4_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_TIM4_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN13)
+#define GPIO_TIM4_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_TIM4_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN13)
+#define GPIO_TIM4_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_TIM4_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_TIM4_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_TIM4_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN14)
+#define GPIO_TIM4_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_TIM4_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_TIM4_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_TIM4_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN15)
+#define GPIO_TIM4_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN0)
+
+#define GPIO_TIM5_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10)
+#define GPIO_TIM5_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM5_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN10)
+#define GPIO_TIM5_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN11)
+#define GPIO_TIM5_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_TIM5_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN11)
+#define GPIO_TIM5_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN12)
+#define GPIO_TIM5_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM5_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN12)
+#define GPIO_TIM5_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM5_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN0)
+#define GPIO_TIM5_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM5_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN0)
+#define GPIO_TIM5_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10)
+
+#define GPIO_TIM8_BKIN_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM8_BKIN_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTI|GPIO_PIN4)
+#define GPIO_TIM8_CH1N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN5)
+#define GPIO_TIM8_CH1N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM8_CH1N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN13)
+#define GPIO_TIM8_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM8_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN5)
+#define GPIO_TIM8_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_TIM8_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN5)
+#define GPIO_TIM8_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM8_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN6)
+#define GPIO_TIM8_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_TIM8_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN6)
+#define GPIO_TIM8_CH2N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN0)
+#define GPIO_TIM8_CH2N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_TIM8_CH2N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN14)
+#define GPIO_TIM8_CH3N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN1)
+#define GPIO_TIM8_CH3N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_TIM8_CH3N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN15)
+#define GPIO_TIM8_CH3IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM8_CH3IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN7)
+#define GPIO_TIM8_CH3OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_TIM8_CH3OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN7)
+#define GPIO_TIM8_CH4IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM8_CH4IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN2)
+#define GPIO_TIM8_CH4OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
+#define GPIO_TIM8_CH4OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN2)
+#define GPIO_TIM8_ETR_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_TIM8_ETR_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN3)
+
+#define GPIO_TIM9_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM9_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_TIM9_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_TIM9_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_TIM9_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM9_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_TIM9_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_TIM9_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN6)
+
+#define GPIO_TIM10_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_TIM10_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN6)
+#define GPIO_TIM10_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
+#define GPIO_TIM10_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN6)
+
+#define GPIO_TIM11_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_TIM11_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN7)
+#define GPIO_TIM11_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
+#define GPIO_TIM11_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN7)
+
+#define GPIO_TIM12_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN6)
+#define GPIO_TIM12_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_TIM12_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6)
+#define GPIO_TIM12_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_TIM12_CH2IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_TIM12_CH2IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN9)
+#define GPIO_TIM12_CH2OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN15)
+#define GPIO_TIM12_CH2OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9)
+
+#define GPIO_TIM13_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM13_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN8)
+#define GPIO_TIM13_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6)
+#define GPIO_TIM13_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN8)
+
+#define GPIO_TIM14_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM14_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN9)
+#define GPIO_TIM14_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7)
+#define GPIO_TIM14_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN9)
+
+/* Trace */
+
+#define GPIO_TRACECLK (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN2)
+#define GPIO_TRACED0 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN3)
+#define GPIO_TRACED1 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN4)
+#define GPIO_TRACED2 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN5)
+#define GPIO_TRACED3 (GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN6)
+#define GPIO_TRACESWO (GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN3)
+
+/* UARTs/USARTs */
+
+#define GPIO_USART1_CK (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN8)
+#define GPIO_USART1_CTS (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN11)
+#define GPIO_USART1_RTS (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN12)
+#define GPIO_USART1_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10)
+#define GPIO_USART1_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7)
+#define GPIO_USART1_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9)
+#define GPIO_USART1_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6)
+
+#define GPIO_USART2_CK_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN4)
+#define GPIO_USART2_CK_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN7)
+#define GPIO_USART2_CTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_USART2_CTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN3)
+#define GPIO_USART2_RTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_USART2_RTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN4)
+#define GPIO_USART2_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
+#define GPIO_USART2_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN6)
+#define GPIO_USART2_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
+#define GPIO_USART2_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN5)
+
+#define GPIO_USART3_CK_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN12)
+#define GPIO_USART3_CK_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTC|GPIO_PIN12)
+#define GPIO_USART3_CK_3 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN10)
+#define GPIO_USART3_CTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN13)
+#define GPIO_USART3_CTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN11)
+#define GPIO_USART3_RTS_1 (GPIO_ALT|GPIO_AF7|GPIO_PORTB|GPIO_PIN14)
+#define GPIO_USART3_RTS_2 (GPIO_ALT|GPIO_AF7|GPIO_PORTD|GPIO_PIN12)
+#define GPIO_USART3_RX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11)
+#define GPIO_USART3_RX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_USART3_RX_3 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN9)
+#define GPIO_USART3_TX_1 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10)
+#define GPIO_USART3_TX_2 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10)
+#define GPIO_USART3_TX_3 (GPIO_ALT|GPIO_AF7|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN8)
+
+#define GPIO_UART4_RX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
+#define GPIO_UART4_RX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11)
+#define GPIO_UART4_TX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
+#define GPIO_UART4_TX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10)
+
+#define GPIO_UART5_RX (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN2)
+#define GPIO_UART5_TX (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN12)
+
+#define GPIO_USART6_CK_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTC|GPIO_PIN8)
+#define GPIO_USART6_CK_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN7)
+#define GPIO_USART6_CTS_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN13)
+#define GPIO_USART6_CTS_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN15)
+#define GPIO_USART6_RTS_1 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN12)
+#define GPIO_USART6_RTS_2 (GPIO_ALT|GPIO_AF8|GPIO_PORTG|GPIO_PIN8)
+#define GPIO_USART6_RX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
+#define GPIO_USART6_RX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN9)
+#define GPIO_USART6_TX_1 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
+#define GPIO_USART6_TX_2 (GPIO_ALT|GPIO_AF8|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_PINMAP_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h
new file mode 100644
index 000000000..04cb05741
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rcc.h
@@ -0,0 +1,506 @@
+/****************************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f40xxx_rcc.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_CHIP_STM32F40XXX_RCC_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RCC_H
+
+/****************************************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************************************/
+
+/* Register Offsets *********************************************************************************/
+
+#define STM32_RCC_CR_OFFSET 0x0000 /* Clock control register */
+#define STM32_RCC_PLLCFG_OFFSET 0x0004 /* PLL configuration register */
+#define STM32_RCC_CFGR_OFFSET 0x0008 /* Clock configuration register */
+#define STM32_RCC_CIR_OFFSET 0x000c /* Clock interrupt register */
+#define STM32_RCC_AHB1RSTR_OFFSET 0x0010 /* AHB1 peripheral reset register */
+#define STM32_RCC_AHB2RSTR_OFFSET 0x0014 /* AHB2 peripheral reset register */
+#define STM32_RCC_AHB3RSTR_OFFSET 0x0018 /* AHB3 peripheral reset register */
+#define STM32_RCC_APB1RSTR_OFFSET 0x0020 /* APB1 Peripheral reset register */
+#define STM32_RCC_APB2RSTR_OFFSET 0x0024 /* APB2 Peripheral reset register */
+#define STM32_RCC_AHB1ENR_OFFSET 0x0030 /* AHB1 Peripheral Clock enable register */
+#define STM32_RCC_AHB2ENR_OFFSET 0x0034 /* AHB2 Peripheral Clock enable register */
+#define STM32_RCC_AHB3ENR_OFFSET 0x0038 /* AHB3 Peripheral Clock enable register */
+#define STM32_RCC_APB1ENR_OFFSET 0x0040 /* APB1 Peripheral Clock enable register */
+#define STM32_RCC_APB2ENR_OFFSET 0x0044 /* APB2 Peripheral Clock enable register */
+#define STM32_RCC_AHB1LPENR_OFFSET 0x0050 /* RCC AHB1 low power modeperipheral clock enable register */
+#define STM32_RCC_AH2BLPENR_OFFSET 0x0054 /* RCC AHB2 low power modeperipheral clock enable register */
+#define STM32_RCC_AH3BLPENR_OFFSET 0x0058 /* RCC AHB3 low power modeperipheral clock enable register */
+#define STM32_RCC_APB1LPENR_OFFSET 0x0060 /* RCC APB1 low power modeperipheral clock enable register */
+#define STM32_RCC_APB2LPENR_OFFSET 0x0060 /* RCC APB2 low power modeperipheral clock enable register */
+#define STM32_RCC_BDCR_OFFSET 0x0070 /* Backup domain control register */
+#define STM32_RCC_CSR_OFFSET 0x0074 /* Control/status register */
+#define STM32_RCC_SSCGR_OFFSET 0x0080 /* Spread spectrum clock generation register */
+#define STM32_RCC_PLLI2SCFGR_OFFSET 0x0084 /* PLLI2S configuration register */
+
+/* Register Addresses *******************************************************************************/
+
+#define STM32_RCC_CR (STM32_RCC_BASE+STM32_RCC_CR_OFFSET)
+#define STM32_RCC_PLLCFG (STM32_RCC_BASE+STM32_RCC_PLLCFG_OFFSET)
+#define STM32_RCC_CFGR (STM32_RCC_BASE+STM32_RCC_CFGR_OFFSET)
+#define STM32_RCC_CIR (STM32_RCC_BASE+STM32_RCC_CIR_OFFSET)
+#define STM32_RCC_AHB1RSTR (STM32_RCC_BASE+STM32_RCC_AHB1RSTR_OFFSET)
+#define STM32_RCC_AHB2RSTR (STM32_RCC_BASE+STM32_RCC_AHB2RSTR_OFFSET)
+#define STM32_RCC_AHB3RSTR (STM32_RCC_BASE+STM32_RCC_AHB3RSTR_OFFSET)
+#define STM32_RCC_APB1RSTR (STM32_RCC_BASE+STM32_RCC_APB1RSTR_OFFSET)
+#define STM32_RCC_APB2RSTR (STM32_RCC_BASE+STM32_RCC_APB2RSTR_OFFSET)
+#define STM32_RCC_AHB1ENR (STM32_RCC_BASE+STM32_RCC_AHB1ENR_OFFSET)
+#define STM32_RCC_AHB2ENR (STM32_RCC_BASE+STM32_RCC_AHB2ENR_OFFSET)
+#define STM32_RCC_AHB3ENR (STM32_RCC_BASE+STM32_RCC_AHB3ENR_OFFSET)
+#define STM32_RCC_APB1ENR (STM32_RCC_BASE+STM32_RCC_APB1ENR_OFFSET)
+#define STM32_RCC_APB2ENR (STM32_RCC_BASE+STM32_RCC_APB2ENR_OFFSET)
+#define STM32_RCC_AHB1LPENR (STM32_RCC_BASE+STM32_RCC_AHB1LPENR_OFFSET)
+#define STM32_RCC_AH2BLPENR (STM32_RCC_BASE+STM32_RCC_AH2BLPENR)
+#define STM32_RCC_AH3BLPENR (STM32_RCC_BASE+STM32_RCC_AH3BLPENR_OFFSET)
+#define STM32_RCC_APB1LPENR (STM32_RCC_BASE+STM32_RCC_APB1LPENR_OFFSET)
+#define STM32_RCC_APB2LPENR (STM32_RCC_BASE+STM32_RCC_APB2LPENR_OFFSET)
+#define STM32_RCC_BDCR (STM32_RCC_BASE+STM32_RCC_BDCR_OFFSET)
+#define STM32_RCC_CSR (STM32_RCC_BASE+STM32_RCC_CSR_OFFSET)
+#define STM32_RCC_SSCGR (STM32_RCC_BASE+STM32_RCC_SSCGR_OFFSET)
+#define STM32_RCC_PLLI2SCFGR (STM32_RCC_BASE+STM32_RCC_PLLI2SCFGR_OFFSET)
+
+/* Register Bitfield Definitions ********************************************************************/
+
+/* Clock control register */
+
+#define RCC_CR_HSION (1 << 0) /* Bit 0: Internal High Speed clock enable */
+#define RCC_CR_HSIRDY (1 << 1) /* Bit 1: Internal High Speed clock ready flag */
+#define RCC_CR_HSITRIM_SHIFT (3) /* Bits 7-3: Internal High Speed clock trimming */
+#define RCC_CR_HSITRIM_MASK (0x1f << RCC_CR_HSITRIM_SHIFT)
+#define RCC_CR_HSICAL_SHIFT (8) /* Bits 15-8: Internal High Speed clock Calibration */
+#define RCC_CR_HSICAL_MASK (0xff << RCC_CR_HSICAL_SHIFT)
+#define RCC_CR_HSEON (1 << 16) /* Bit 16: External High Speed clock enable */
+#define RCC_CR_HSERDY (1 << 17) /* Bit 17: External High Speed clock ready flag */
+#define RCC_CR_HSEBYP (1 << 18) /* Bit 18: External High Speed clock Bypass */
+#define RCC_CR_CSSON (1 << 19) /* Bit 19: Clock Security System enable */
+#define RCC_CR_PLLON (1 << 24) /* Bit 24: PLL enable */
+#define RCC_CR_PLLRDY (1 << 25) /* Bit 25: PLL clock ready flag */
+#define RCC_CR_PLLI2SON (1 << 26) /* Bit 26: PLLI2S enable */
+#define RCC_CR_PLLI2SRDY (1 << 27) /* Bit 27: PLLI2S clock ready flag */
+
+/* PLL configuration register */
+
+#define RCC_PLLCFG_PLLM_SHIFT (0) /* Bits 0-5: Main PLL (PLL) and audio PLL (PLLI2S)
+ * input clock divider */
+#define RCC_PLLCFG_PLLM_MASK (0x3f << RCC_PLLCFG_PLLM_SHIFT)
+# define RCC_PLLCFG_PLLM(n) ((n) << RCC_PLLCFG_PLLM_SHIFT) /* n = 2..63 */
+#define RCC_PLLCFG_PLLN_SHIFT (6) /* Bits 6-14: Main PLL (PLL) VCO multiplier */
+#define RCC_PLLCFG_PLLN_MASK (0x1ff << RCC_PLLCFG_PLLN_SHIFT)
+# define RCC_PLLCFG_PLLN(n) ((n) << RCC_PLLCFG_PLLN_SHIFT) /* n = 2..432 */
+#define RCC_PLLCFG_PLLP_SHIFT (16) /* Bits 16-17: Main PLL (PLL) main system clock divider */
+#define RCC_PLLCFG_PLLP_MASK (3 << RCC_PLLCFG_PLLP_SHIFT)
+# define RCC_PLLCFG_PLLP(n) ((((n)>>1)-1)<< RCC_PLLCFG_PLLP_SHIFT) /* n=2,4,6,8 */
+# define RCC_PLLCFG_PLLP_2 (0 << RCC_PLLCFG_PLLP_SHIFT) /* 00: PLLP = 2 */
+# define RCC_PLLCFG_PLLP_4 (1 << RCC_PLLCFG_PLLP_SHIFT) /* 01: PLLP = 4 */
+# define RCC_PLLCFG_PLLP_6 (2 << RCC_PLLCFG_PLLP_SHIFT) /* 10: PLLP = 6 */
+# define RCC_PLLCFG_PLLP_8 (3 << RCC_PLLCFG_PLLP_SHIFT) /* 11: PLLP = 8 */
+#define RCC_PLLCFG_PLLSRC (1 << 22) /* Bit 22: Main PLL(PLL) and audio PLL (PLLI2S)
+ * entry clock source */
+# define RCC_PLLCFG_PLLSRC_HSI (0)
+# define RCC_PLLCFG_PLLSRC_HSE RCC_PLLCFG_PLLSRC
+#define RCC_PLLCFG_PLLQ_SHIFT (24) /* Bits 24-27: Main PLL (PLL) divider
+ * (USB OTG FS, SDIO and RNG clocks) */
+#define RCC_PLLCFG_PLLQ_MASK (15 << RCC_PLLCFG_PLLQ_SHIFT)
+# define RCC_PLLCFG_PLLQ(n) ((n) << RCC_PLLCFG_PLLQ_SHIFT) /* n=2..15 */
+
+#define RCC_PLLCFG_RESET (0x24003010) /* PLLCFG reset value */
+
+/* Clock configuration register */
+
+#define RCC_CFGR_SW_SHIFT (0) /* Bits 0-1: System clock Switch */
+#define RCC_CFGR_SW_MASK (3 << RCC_CFGR_SW_SHIFT)
+# define RCC_CFGR_SW_HSI (0 << RCC_CFGR_SW_SHIFT) /* 00: HSI selected as system clock */
+# define RCC_CFGR_SW_HSE (1 << RCC_CFGR_SW_SHIFT) /* 01: HSE selected as system clock */
+# define RCC_CFGR_SW_PLL (2 << RCC_CFGR_SW_SHIFT) /* 10: PLL selected as system clock */
+#define RCC_CFGR_SWS_SHIFT (2) /* Bits 2-3: System Clock Switch Status */
+#define RCC_CFGR_SWS_MASK (3 << RCC_CFGR_SWS_SHIFT)
+# define RCC_CFGR_SWS_HSI (0 << RCC_CFGR_SWS_SHIFT) /* 00: HSI oscillator used as system clock */
+# define RCC_CFGR_SWS_HSE (1 << RCC_CFGR_SWS_SHIFT) /* 01: HSE oscillator used as system clock */
+# define RCC_CFGR_SWS_PLL (2 << RCC_CFGR_SWS_SHIFT) /* 10: PLL used as system clock */
+#define RCC_CFGR_HPRE_SHIFT (4) /* Bits 4-7: AHB prescaler */
+#define RCC_CFGR_HPRE_MASK (0x0f << RCC_CFGR_HPRE_SHIFT)
+# define RCC_CFGR_HPRE_SYSCLK (0 << RCC_CFGR_HPRE_SHIFT) /* 0xxx: SYSCLK not divided */
+# define RCC_CFGR_HPRE_SYSCLKd2 (8 << RCC_CFGR_HPRE_SHIFT) /* 1000: SYSCLK divided by 2 */
+# define RCC_CFGR_HPRE_SYSCLKd4 (9 << RCC_CFGR_HPRE_SHIFT) /* 1001: SYSCLK divided by 4 */
+# define RCC_CFGR_HPRE_SYSCLKd8 (10 << RCC_CFGR_HPRE_SHIFT) /* 1010: SYSCLK divided by 8 */
+# define RCC_CFGR_HPRE_SYSCLKd16 (11 << RCC_CFGR_HPRE_SHIFT) /* 1011: SYSCLK divided by 16 */
+# define RCC_CFGR_HPRE_SYSCLKd64 (12 << RCC_CFGR_HPRE_SHIFT) /* 1100: SYSCLK divided by 64 */
+# define RCC_CFGR_HPRE_SYSCLKd128 (13 << RCC_CFGR_HPRE_SHIFT) /* 1101: SYSCLK divided by 128 */
+# define RCC_CFGR_HPRE_SYSCLKd256 (14 << RCC_CFGR_HPRE_SHIFT) /* 1110: SYSCLK divided by 256 */
+# define RCC_CFGR_HPRE_SYSCLKd512 (15 << RCC_CFGR_HPRE_SHIFT) /* 1111: SYSCLK divided by 512 */
+#define RCC_CFGR_PPRE1_SHIFT (10) /* Bits 10-12: APB Low speed prescaler (APB1) */
+#define RCC_CFGR_PPRE1_MASK (7 << RCC_CFGR_PPRE1_SHIFT)
+# define RCC_CFGR_PPRE1_HCLK (0 << RCC_CFGR_PPRE1_SHIFT) /* 0xx: HCLK not divided */
+# define RCC_CFGR_PPRE1_HCLKd2 (4 << RCC_CFGR_PPRE1_SHIFT) /* 100: HCLK divided by 2 */
+# define RCC_CFGR_PPRE1_HCLKd4 (5 << RCC_CFGR_PPRE1_SHIFT) /* 101: HCLK divided by 4 */
+# define RCC_CFGR_PPRE1_HCLKd8 (6 << RCC_CFGR_PPRE1_SHIFT) /* 110: HCLK divided by 8 */
+# define RCC_CFGR_PPRE1_HCLKd16 (7 << RCC_CFGR_PPRE1_SHIFT) /* 111: HCLK divided by 16 */
+#define RCC_CFGR_PPRE2_SHIFT (13) /* Bits 13-15: APB High speed prescaler (APB2) */
+#define RCC_CFGR_PPRE2_MASK (7 << RCC_CFGR_PPRE2_SHIFT)
+# define RCC_CFGR_PPRE2_HCLK (0 << RCC_CFGR_PPRE2_SHIFT) /* 0xx: HCLK not divided */
+# define RCC_CFGR_PPRE2_HCLKd2 (4 << RCC_CFGR_PPRE2_SHIFT) /* 100: HCLK divided by 2 */
+# define RCC_CFGR_PPRE2_HCLKd4 (5 << RCC_CFGR_PPRE2_SHIFT) /* 101: HCLK divided by 4 */
+# define RCC_CFGR_PPRE2_HCLKd8 (6 << RCC_CFGR_PPRE2_SHIFT) /* 110: HCLK divided by 8 */
+# define RCC_CFGR_PPRE2_HCLKd16 (7 << RCC_CFGR_PPRE2_SHIFT) /* 111: HCLK divided by 16 */
+#define RCC_CFGR_RTCPRE_SHIFT (16) /* Bits 16-20: APB High speed prescaler (APB2) */
+#define RCC_CFGR_RTCPRE_MASK (31 << RCC_CFGR_RTCPRE)
+# define RCC_CFGR_RTCPRE(n) ((n) << RCC_CFGR_RTCPRE) /* HSE/n, n=1..31 */
+#define RCC_CFGR_MCO1_SHIFT (21) /* Bits 21-22: Microcontroller Clock Output */
+#define RCC_CFGR_MCO1_MASK (3 << RCC_CFGR_MCO1_SHIFT)
+# define RCC_CFGR_MCO1_HSI (0 << RCC_CFGR_MCO1_SHIFT) /* 00: HSI clock selected */
+# define RCC_CFGR_MCO1_LSE (1 << RCC_CFGR_MCO1_SHIFT) /* 01: LSE oscillator selected */
+# define RCC_CFGR_MCO1_HSE (2 << RCC_CFGR_MCO1_SHIFT) /* 10: HSE oscillator clock selected */
+# define RCC_CFGR_MCO1_PLL (3 << RCC_CFGR_MCO1_SHIFT) /* 11: PLL clock selected */
+#define TCC_CFGR_I2SSRC (1 << 23) /* Bit 23: I2S clock selection */
+#define RCC_CFGR_MCO1PRE_SHIFT (24) /* Bits 24-26: MCO1 prescaler */
+#define RCC_CFGR_MCO1PRE_MASK (7 << RCC_CFGR_MCO1PRE_SHIFT)
+# define RCC_CFGR_MCO1PRE_NONE (0 << RCC_CFGR_MCO1PRE_SHIFT) /* 0xx: no division */
+# define RCC_CFGR_MCO1PRE_DIV2 (4 << RCC_CFGR_MCO1PRE_SHIFT) /* 100: division by 2 */
+# define RCC_CFGR_MCO1PRE_DIV3 (5 << RCC_CFGR_MCO1PRE_SHIFT) /* 101: division by 3 */
+# define RCC_CFGR_MCO1PRE_DIV4 (6 << RCC_CFGR_MCO1PRE_SHIFT) /* 110: division by 4 */
+# define RCC_CFGR_MCO1PRE_DIV5 (7 << RCC_CFGR_MCO1PRE_SHIFT) /* 111: division by 5 */
+#define RCC_CFGR_MCO2PRE_SHIFT (27) /* Bits 27-29: MCO2 prescaler */
+#define RCC_CFGR_MCO2PRE_MASK (7 << RCC_CFGR_MCO2PRE_SHIFT)
+# define RCC_CFGR_MCO2PRE_NONE (0 << RCC_CFGR_MCO2PRE_SHIFT) /* 0xx: no division */
+# define RCC_CFGR_MCO2PRE_DIV2 (4 << RCC_CFGR_MCO2PRE_SHIFT) /* 100: division by 2 */
+# define RCC_CFGR_MCO2PRE_DIV3 (5 << RCC_CFGR_MCO2PRE_SHIFT) /* 101: division by 3 */
+# define RCC_CFGR_MCO2PRE_DIV4 (6 << RCC_CFGR_MCO2PRE_SHIFT) /* 110: division by 4 */
+# define RCC_CFGR_MCO2PRE_DIV5 (7 << RCC_CFGR_MCO2PRE_SHIFT) /* 111: division by 5 */
+#define RCC_CFGR_MCO2_SHIFT (30) /* Bits 30-31: Microcontroller clock output 2 */
+#define RCC_CFGR_MCO2_MASK (3 << RCC_CFGR_MCO2_SHIFT)
+# define RCC_CFGR_MCO2_SYSCLK (0 << RCC_CFGR_MCO2_SHIFT) /* 00: System clock (SYSCLK) selected */
+# define RCC_CFGR_MCO2_PLLI2S (1 << RCC_CFGR_MCO2_SHIFT) /* 01: PLLI2S clock selected */
+# define RCC_CFGR_MCO2_HSE (2 << RCC_CFGR_MCO2_SHIFT) /* 10: HSE oscillator clock selected */
+# define RCC_CFGR_MCO2_PLL (3 << RCC_CFGR_MCO2_SHIFT) /* 11: PLL clock selected */
+
+/* Clock interrupt register */
+
+#define RCC_CIR_LSIRDYF (1 << 0) /* Bit 0: LSI Ready Interrupt flag */
+#define RCC_CIR_LSERDYF (1 << 1) /* Bit 1: LSE Ready Interrupt flag */
+#define RCC_CIR_HSIRDYF (1 << 2) /* Bit 2: HSI Ready Interrupt flag */
+#define RCC_CIR_HSERDYF (1 << 3) /* Bit 3: HSE Ready Interrupt flag */
+#define RCC_CIR_PLLRDYF (1 << 4) /* Bit 4: PLL Ready Interrupt flag */
+#define RCC_CIR_PLLI2SRDYF (1 << 5) /* Bit 5: PLLI2S Ready Interrupt flag */
+#define RCC_CIR_CSSF (1 << 7) /* Bit 7: Clock Security System Interrupt flag */
+#define RCC_CIR_LSIRDYIE (1 << 8) /* Bit 8: LSI Ready Interrupt Enable */
+#define RCC_CIR_LSERDYIE (1 << 9) /* Bit 9: LSE Ready Interrupt Enable */
+#define RCC_CIR_HSIRDYIE (1 << 10) /* Bit 10: HSI Ready Interrupt Enable */
+#define RCC_CIR_HSERDYIE (1 << 11) /* Bit 11: HSE Ready Interrupt Enable */
+#define RCC_CIR_PLLRDYIE (1 << 12) /* Bit 12: PLL Ready Interrupt Enable */
+#define RCC_CIR_PLLI2SRDYIE (1 << 13) /* Bit 13: PLLI2S Ready Interrupt enable */
+#define RCC_CIR_LSIRDYC (1 << 16) /* Bit 16: LSI Ready Interrupt Clear */
+#define RCC_CIR_LSERDYC (1 << 17) /* Bit 17: LSE Ready Interrupt Clear */
+#define RCC_CIR_HSIRDYC (1 << 18) /* Bit 18: HSI Ready Interrupt Clear */
+#define RCC_CIR_HSERDYC (1 << 19) /* Bit 19: HSE Ready Interrupt Clear */
+#define RCC_CIR_PLLRDYC (1 << 20) /* Bit 20: PLL Ready Interrupt Clear */
+#define RCC_CIR_PLLI2SRDYC (1 << 21) /* Bit 21: PLLI2S Ready Interrupt clear */
+#define RCC_CIR_CSSC (1 << 23) /* Bit 23: Clock Security System Interrupt Clear */
+
+/* AHB1 peripheral reset register */
+
+#define RCC_AHB1RSTR_GPIOARST (1 << 0) /* Bit 0: IO port A reset */
+#define RCC_AHB1RSTR_GPIOBRST (1 << 1) /* Bit 1: IO port B reset */
+#define RCC_AHB1RSTR_GPIOCRST (1 << 2) /* Bit 2: IO port C reset */
+#define RCC_AHB1RSTR_GPIODRST (1 << 3) /* Bit 3: IO port D reset */
+#define RCC_AHB1RSTR_GPIOERST (1 << 4) /* Bit 4: IO port E reset */
+#define RCC_AHB1RSTR_GPIOFRST (1 << 5) /* Bit 5: IO port F reset */
+#define RCC_AHB1RSTR_GPIOGRST (1 << 6) /* Bit 6: IO port G reset */
+#define RCC_AHB1RSTR_GPIOHRST (1 << 7) /* Bit 7: IO port H reset */
+#define RCC_AHB1RSTR_CRCRST (1 << 12) /* Bit 12 IO port I reset */
+#define RCC_AHB1RSTR_DMA1RST (1 << 21) /* Bit 21: DMA1 reset */
+#define RCC_AHB1RSTR_DMA2RST (1 << 22) /* Bit 22: DMA2 reset */
+#define RCC_AHB1RSTR_ETHMACRST (1 << 25) /* Bit 25: Ethernet MAC reset */
+#define RCC_AHB1RSTR_OTGHSRST (1 << 29) /* Bit 29: USB OTG HS module reset */
+
+/* AHB2 peripheral reset register */
+
+#define RCC_AHB2RSTR_DCMIRST (1 << 0) /* Bit 0: Camera interface reset */
+#define RCC_AHB2RSTR_CRYPRST (1 << 4) /* Bit 4: Cryptographic module reset */
+#define RCC_AHB2RSTR_HASHRST (1 << 5) /* Bit 5: Hash module reset */
+#define RCC_AHB2RSTR_RNGRST (1 << 6) /* Bit 6: Random number generator module reset */
+#define RCC_AHB2RSTR_OTGFSRST (1 << 7) /* Bit 7: USB OTG FS module reset */
+
+/* AHB3 peripheral reset register */
+
+#define RCC_AHB3RSTR_FSMCRST (1 << 0) /* Bit 0: Flexible static memory controller module reset */
+
+/* APB1 Peripheral reset register */
+
+#define RCC_APB1RSTR_TIM2RST (1 << 0) /* Bit 0: TIM2 reset */
+#define RCC_APB1RSTR_TIM3RST (1 << 1) /* Bit 1: TIM3 reset */
+#define RCC_APB1RSTR_TIM4RST (1 << 2) /* Bit 2: TIM4 reset */
+#define RCC_APB1RSTR_TIM5RST (1 << 3) /* Bit 3: TIM5 reset */
+#define RCC_APB1RSTR_TIM6RST (1 << 4) /* Bit 4: TIM6 reset */
+#define RCC_APB1RSTR_TIM7RST (1 << 5) /* Bit 5: TIM7 reset */
+#define RCC_APB1RSTR_TIM12RST (1 << 6) /* Bit 6: TIM12 reset */
+#define RCC_APB1RSTR_TIM13RST (1 << 7) /* Bit 7: TIM13 reset */
+#define RCC_APB1RSTR_TIM14RST (1 << 8) /* Bit 8: TIM14 reset */
+#define RCC_APB1RSTR_WWDGRST (1 << 11) /* Bit 11: Window watchdog reset */
+#define RCC_APB1RSTR_SPI2RST (1 << 14) /* Bit 14: SPI 2 reset */
+#define RCC_APB1RSTR_SPI3RST (1 << 15) /* Bit 15: SPI 3 reset */
+#define RCC_APB1RSTR_USART2RST (1 << 17) /* Bit 17: USART 2 reset */
+#define RCC_APB1RSTR_USART3RST (1 << 18) /* Bit 18: USART 3 reset */
+#define RCC_APB1RSTR_UART4RST (1 << 19) /* Bit 19: USART 4 reset */
+#define RCC_APB1RSTR_UART5RST (1 << 20) /* Bit 20: USART 5 reset */
+#define RCC_APB1RSTR_I2C1RST (1 << 21) /* Bit 21: I2C 1 reset */
+#define RCC_APB1RSTR_I2C2RST (1 << 22) /* Bit 22: I2C 2 reset */
+#define RCC_APB1RSTR_I2C3RST (1 << 23) /* Bit 23: I2C3 reset */
+#define RCC_APB1RSTR_CAN1RST (1 << 25) /* Bit 25: CAN1 reset */
+#define RCC_APB1RSTR_CAN2RST (1 << 26) /* Bit 26: CAN2 reset */
+#define RCC_APB1RSTR_PWRRST (1 << 28) /* Bit 28: Power interface reset */
+#define RCC_APB1RSTR_DACRST (1 << 29) /* Bit 29: DAC reset */
+
+/* APB2 Peripheral reset register */
+
+#define RCC_APB2RSTR_TIM1RST (1 << 0) /* Bit 0: TIM1 reset */
+#define RCC_APB2RSTR_TIM8RST (1 << 1) /* Bit 1: TIM8 reset */
+#define RCC_APB2RSTR_USART1RST (1 << 4) /* Bit 4: USART1 reset */
+#define RCC_APB2RSTR_USART6RST (1 << 5) /* Bit 5: USART6 reset */
+#define RCC_APB2RSTR_ADCRST (1 << 8) /* Bit 8: ADC interface reset (common to all ADCs) */
+#define RCC_APB2RSTR_SDIORST (1 << 11) /* Bit 11: SDIO reset */
+#define RCC_APB2RSTR_SPI1RST (1 << 12) /* Bit 12: SPI 1 reset */
+#define RCC_APB2RSTR_SYSCFGRST (1 << 14) /* Bit 14: System configuration controller reset */
+#define RCC_APB2RSTR_TIM9RST (1 << 16) /* Bit 16: TIM9 reset */
+#define RCC_APB2RSTR_TIM10RST (1 << 17) /* Bit 17: TIM10 reset */
+#define RCC_APB2RSTR_TIM11RST (1 << 18) /* Bit 18: TIM11 reset */
+
+/* AHB1 Peripheral Clock enable register */
+
+#define RCC_AHB1ENR_GPIOEN(n) (1 << (n))
+#define RCC_AHB1ENR_GPIOAEN (1 << 0) /* Bit 0: IO port A clock enable */
+#define RCC_AHB1ENR_GPIOBEN (1 << 1) /* Bit 1: IO port B clock enable */
+#define RCC_AHB1ENR_GPIOCEN (1 << 2) /* Bit 2: IO port C clock enable */
+#define RCC_AHB1ENR_GPIODEN (1 << 3) /* Bit 3: IO port D clock enable */
+#define RCC_AHB1ENR_GPIOEEN (1 << 4) /* Bit 4: IO port E clock enable */
+#define RCC_AHB1ENR_GPIOFEN (1 << 5) /* Bit 5: IO port F clock enable */
+#define RCC_AHB1ENR_GPIOGEN (1 << 6) /* Bit 6: IO port G clock enable */
+#define RCC_AHB1ENR_GPIOHEN (1 << 7) /* Bit 7: IO port H clock enable */
+#define RCC_AHB1ENR_GPIOIEN (1 << 8) /* Bit 8: IO port I clock enable */
+#define RCC_AHB1ENR_CRCEN (1 << 12) /* Bit 12: CRC clock enable */
+#define RCC_AHB1ENR_BKPSRAMEN (1 << 18) /* Bit 18: Backup SRAM interface clock enable */
+#define RCC_AHB1ENR_CCMDATARAMEN (1 << 20) /* Bit 20: CCM data RAM clock enable */
+#define RCC_AHB1ENR_DMA1EN (1 << 21) /* Bit 21: DMA1 clock enable */
+#define RCC_AHB1ENR_DMA2EN (1 << 22) /* Bit 22: DMA2 clock enable */
+#define RCC_AHB1ENR_ETHMACEN (1 << 25) /* Bit 25: Ethernet MAC clock enable */
+#define RCC_AHB1ENR_ETHMACTXEN (1 << 26) /* Bit 26: Ethernet Transmission clock enable */
+#define RCC_AHB1ENR_ETHMACRXEN (1 << 27) /* Bit 27: Ethernet Reception clock enable */
+#define RCC_AHB1ENR_ETHMACPTPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable */
+#define RCC_AHB1ENR_OTGHSEN (1 << 29) /* Bit 29: USB OTG HS clock enable */
+#define RCC_AHB1ENR_OTGHSULPIEN (1 << 30) /* Bit 30: USB OTG HSULPI clock enable */
+
+/* AHB2 Peripheral Clock enable register */
+
+#define RCC_AHB2ENR_DCMIEN (1 << 0) /* Bit 0: Camera interface enable */
+#define RCC_AHB2ENR_CRYPEN (1 << 4) /* Bit 4: Cryptographic modules clock enable */
+#define RCC_AHB2ENR_HASHEN (1 << 5) /* Bit 5: Hash modules clock enable */
+#define RCC_AHB2ENR_RNGEN (1 << 6) /* Bit 6: Random number generator clock enable */
+#define RCC_AHB2ENR_OTGFSEN (1 << 7) /* Bit 7: USB OTG FS clock enable */
+
+/* AHB3 Peripheral Clock enable register */
+
+#define RCC_AHB3ENR_FSMCEN (1 << 0) /* Bit 0: Flexible static memory controller module clock enable */
+
+/* APB1 Peripheral Clock enable register */
+
+#define RCC_APB1ENR_TIM2EN (1 << 0) /* Bit 0: TIM2 clock enable */
+#define RCC_APB1ENR_TIM3EN (1 << 1) /* Bit 1: TIM3 clock enable */
+#define RCC_APB1ENR_TIM4EN (1 << 2) /* Bit 2: TIM4 clock enable */
+#define RCC_APB1ENR_TIM5EN (1 << 3) /* Bit 3: TIM5 clock enable */
+#define RCC_APB1ENR_TIM6EN (1 << 4) /* Bit 4: TIM6 clock enable */
+#define RCC_APB1ENR_TIM7EN (1 << 5) /* Bit 5: TIM7 clock enable */
+#define RCC_APB1ENR_TIM12EN (1 << 6) /* Bit 6: TIM12 clock enable */
+#define RCC_APB1ENR_TIM13EN (1 << 7) /* Bit 7: TIM13 clock enable */
+#define RCC_APB1ENR_TIM14EN (1 << 8) /* Bit 8: TIM14 clock enable */
+#define RCC_APB1ENR_WWDGEN (1 << 11) /* Bit 11: Window watchdog clock enable */
+#define RCC_APB1ENR_SPI2EN (1 << 14) /* Bit 14: SPI2 clock enable */
+#define RCC_APB1ENR_SPI3EN (1 << 15) /* Bit 15: SPI3 clock enable */
+#define RCC_APB1ENR_USART2EN (1 << 17) /* Bit 17: USART 2 clock enable */
+#define RCC_APB1ENR_USART3EN (1 << 18) /* Bit 18: USART3 clock enable */
+#define RCC_APB1ENR_UART4EN (1 << 19) /* Bit 19: UART4 clock enable */
+#define RCC_APB1ENR_UART5EN (1 << 20) /* Bit 20: UART5 clock enable */
+#define RCC_APB1ENR_I2C1EN (1 << 21) /* Bit 21: I2C1 clock enable */
+#define RCC_APB1ENR_I2C2EN (1 << 22) /* Bit 22: I2C2 clock enable */
+#define RCC_APB1ENR_I2C3EN (1 << 23) /* Bit 23: I2C3 clock enable */
+#define RCC_APB1ENR_CAN1EN (1 << 25) /* Bit 25: CAN 1 clock enable */
+#define RCC_APB1ENR_CAN2EN (1 << 26) /* Bit 26: CAN 2 clock enable */
+#define RCC_APB1ENR_PWREN (1 << 28) /* Bit 28: Power interface clock enable */
+#define RCC_APB1ENR_DACEN (1 << 29) /* Bit 29: DAC interface clock enable */
+
+/* APB2 Peripheral Clock enable register */
+
+#define RCC_APB2ENR_TIM1EN (1 << 0) /* Bit 0: TIM1 clock enable */
+#define RCC_APB2ENR_TIM8EN (1 << 1) /* Bit 1: TIM8 clock enable */
+#define RCC_APB2ENR_USART1EN (1 << 4) /* Bit 4: USART1 clock enable */
+#define RCC_APB2ENR_USART6EN (1 << 5) /* Bit 5: USART6 clock enable */
+#define RCC_APB2ENR_ADC1EN (1 << 8) /* Bit 8: ADC1 clock enable */
+#define RCC_APB2ENR_ADC2EN (1 << 9) /* Bit 9: ADC2 clock enable */
+#define RCC_APB2ENR_ADC3EN (1 << 10) /* Bit 10: ADC3 clock enable */
+#define RCC_APB2ENR_SDIOEN (1 << 11) /* Bit 11: SDIO clock enable */
+#define RCC_APB2ENR_SPI1EN (1 << 12) /* Bit 12: SPI1 clock enable */
+#define RCC_APB2ENR_SYSCFGEN (1 << 14) /* Bit 14: System configuration controller clock enable */
+#define RCC_APB2ENR_TIM9EN (1 << 16) /* Bit 16: TIM9 clock enable */
+#define RCC_APB2ENR_TIM10EN (1 << 17) /* Bit 17: TIM10 clock enable */
+#define RCC_APB2ENR_TIM11EN (1 << 18) /* Bit 18: TIM11 clock enable */
+
+/* RCC AHB1 low power modeperipheral clock enable register */
+
+#define RCC_AHB1LPENR_GPIOLPEN(n) (1 << (n))
+#define RCC_AHB1LPENR_GPIOALPEN (1 << 0) /* Bit 0: IO port A clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOBLPEN (1 << 1) /* Bit 1: IO port B clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOCLPEN (1 << 2) /* Bit 2: IO port C clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIODLPEN (1 << 3) /* Bit 3: IO port D clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOELPEN (1 << 4) /* Bit 4: IO port E clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOFLPEN (1 << 5) /* Bit 5: IO port F clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOGLPEN (1 << 6) /* Bit 6: IO port G clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOHLPEN (1 << 7) /* Bit 7: IO port H clock enable during Sleep mode */
+#define RCC_AHB1LPENR_GPIOILPEN (1 << 8) /* Bit 8: IO port I clock enable during Sleep mode */
+#define RCC_AHB1LPENR_CRCLPEN (1 << 12) /* Bit 12: CRC clock enable during Sleep mode */
+#define RCC_AHB1LPENR_FLITFLPEN (1 << 15) /* Bit 15: Flash interface clock enable during Sleep mode */
+#define RCC_AHB1LPENR_SRAM1LPEN (1 << 16) /* Bit 16: SRAM 1 interface clock enable during Sleep mode */
+#define RCC_AHB1LPENR_SRAM2LPEN (1 << 17) /* Bit 17: SRAM 2 interface clock enable during Sleep mode */
+#define RCC_AHB1LPENR_BKPSRAMLPEN (1 << 18) /* Bit 18: Backup SRAM interface clock enable during Sleep mode */
+#define RCC_AHB1LPENR_CCMDATARAMLPEN (1 << 20) /* Bit 20: CCM data RAM clock enable during Sleep mode */
+#define RCC_AHB1LPENR_DMA1LPEN (1 << 21) /* Bit 21: DMA1 clock enable during Sleep mode */
+#define RCC_AHB1LPENR_DMA2LPEN (1 << 22) /* Bit 22: DMA2 clock enable during Sleep mode */
+#define RCC_AHB1LPENR_ETHMACLPEN (1 << 25) /* Bit 25: Ethernet MAC clock enable during Sleep mode */
+#define RCC_AHB1LPENR_ETHMACTXLPEN (1 << 26) /* Bit 26: Ethernet Transmission clock enable during Sleep mode */
+#define RCC_AHB1LPENR_ETHMACRXLPEN (1 << 27) /* Bit 27: Ethernet Reception clock enable during Sleep mode */
+#define RCC_AHB1LPENR_ETHMACPTPLPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable during Sleep mode */
+#define RCC_AHB1LPENR_OTGHSLPEN (1 << 29) /* Bit 29: USB OTG HS clock enable during Sleep mode */
+#define RCC_AHB1LPENR_OTGHSULPILPEN (1 << 30) /* Bit 30: USB OTG HSULPI clock enable during Sleep mode */
+
+/* RCC AHB2 low power modeperipheral clock enable register */
+
+#define RCC_AHB2LPENR_DCMILPEN (1 << 0) /* Bit 0: Camera interface enable during Sleep mode */
+#define RCC_AHB2LPENR_CRYPLPEN (1 << 4) /* Bit 4: Cryptographic modules clock enable during Sleep mode */
+#define RCC_AHB2LPENR_HASHLPEN (1 << 5) /* Bit 5: Hash modules clock enable during Sleep mode */
+#define RCC_AHB2LPENR_RNGLPEN (1 << 6) /* Bit 6: Random number generator clock enable during Sleep mode */
+#define RCC_AHB2LPENR_OTGFLPSEN (1 << 7) /* Bit 7: USB OTG FS clock enable during Sleep mode */
+
+/* RCC AHB3 low power modeperipheral clock enable register */
+
+#define RCC_AHB3LPENR_FSMLPEN (1 << 0) /* Bit 0: Flexible static memory controller module clock
+ * enable during Sleep mode */
+
+/* RCC APB1 low power modeperipheral clock enable register */
+
+#define RCC_APB1LPENR_TIM2LPEN (1 << 0) /* Bit 0: TIM2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM3LPEN (1 << 1) /* Bit 1: TIM3 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM4LPEN (1 << 2) /* Bit 2: TIM4 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM5LPEN (1 << 3) /* Bit 3: TIM5 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM6LPEN (1 << 4) /* Bit 4: TIM6 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM7LPEN (1 << 5) /* Bit 5: TIM7 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM12LPEN (1 << 6) /* Bit 6: TIM12 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM13LPEN (1 << 7) /* Bit 7: TIM13 clock enable during Sleep mode */
+#define RCC_APB1LPENR_TIM14LPEN (1 << 8) /* Bit 8: TIM14 clock enable during Sleep mode */
+#define RCC_APB1LPENR_WWDGLPEN (1 << 11) /* Bit 11: Window watchdog clock enable during Sleep mode */
+#define RCC_APB1LPENR_SPI2LPEN (1 << 14) /* Bit 14: SPI2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_SPI3LPEN (1 << 15) /* Bit 15: SPI3 clock enable during Sleep mode */
+#define RCC_APB1LPENR_USART2LPEN (1 << 17) /* Bit 17: USART 2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_USART3LPEN (1 << 18) /* Bit 18: USART3 clock enable during Sleep mode */
+#define RCC_APB1LPENR_UART4LPEN (1 << 19) /* Bit 19: UART4 clock enable during Sleep mode */
+#define RCC_APB1LPENR_UART5LPEN (1 << 20) /* Bit 20: UART5 clock enable during Sleep mode */
+#define RCC_APB1LPENR_I2C1LPEN (1 << 21) /* Bit 21: I2C1 clock enable during Sleep mode */
+#define RCC_APB1LPENR_I2C2LPEN (1 << 22) /* Bit 22: I2C2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_I2C3LPEN (1 << 23) /* Bit 23: I2C3 clock enable during Sleep mode */
+#define RCC_APB1LPENR_CAN1LPEN (1 << 25) /* Bit 25: CAN 1 clock enable during Sleep mode */
+#define RCC_APB1LPENR_CAN2LPEN (1 << 26) /* Bit 26: CAN 2 clock enable during Sleep mode */
+#define RCC_APB1LPENR_PWRLPEN (1 << 28) /* Bit 28: Power interface clock enable during Sleep mode */
+#define RCC_APB1LPENR_DACLPEN (1 << 29) /* Bit 29: DAC interface clock enable during Sleep mode */
+
+/* RCC APB2 low power modeperipheral clock enable register */
+
+#define RCC_APB2LPENR_TIM1LPEN (1 << 0) /* Bit 0: TIM1 clock enable during Sleep mode */
+#define RCC_APB2LPENR_TIM8LPEN (1 << 1) /* Bit 1: TIM8 clock enable during Sleep mode */
+#define RCC_APB2LPENR_USART1LPEN (1 << 4) /* Bit 4: USART1 clock enable during Sleep mode */
+#define RCC_APB2LPENR_USART6LPEN (1 << 5) /* Bit 5: USART6 clock enable during Sleep mode */
+#define RCC_APB2LPENR_ADC1LPEN (1 << 8) /* Bit 8: ADC1 clock enable during Sleep mode */
+#define RCC_APB2LPENR_ADC2LPEN (1 << 9) /* Bit 9: ADC2 clock enable during Sleep mode */
+#define RCC_APB2LPENR_ADC3LPEN (1 << 10) /* Bit 10: ADC3 clock enable during Sleep mode */
+#define RCC_APB2LPENR_SDIOLPEN (1 << 11) /* Bit 11: SDIO clock enable during Sleep mode */
+#define RCC_APB2LPENR_SPI1LPEN (1 << 12) /* Bit 12: SPI1 clock enable during Sleep mode */
+#define RCC_APB2LPENR_SYSCFGLPEN (1 << 14) /* Bit 14: System configuration controller clock enable during Sleep mode */
+#define RCC_APB2LPENR_TIM9LPEN (1 << 16) /* Bit 16: TIM9 clock enable during Sleep mode */
+#define RCC_APB2LPENR_TIM10LPEN (1 << 17) /* Bit 17: TIM10 clock enable during Sleep mode */
+#define RCC_APB2LPENR_TIM11LPEN (1 << 18) /* Bit 18: TIM11 clock enable during Sleep mode */
+
+/* Backup domain control register */
+
+#define RCC_BDCR_LSEON (1 << 0) /* Bit 0: External Low Speed oscillator enable */
+#define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */
+#define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */
+#define RCC_BDCR_RTCSEL_SHIFT (8) /* Bits 9:8: RTC clock source selection */
+#define RCC_BDCR_RTCSEL_MASK (3 << RCC_BDCR_RTCSEL_SHIFT)
+# define RCC_BDCR_RTCSEL_NOCLK (0 << RCC_BDCR_RTCSEL_SHIFT) /* 00: No clock */
+# define RCC_BDCR_RTCSEL_LSE (1 << RCC_BDCR_RTCSEL_SHIFT) /* 01: LSE oscillator clock used as RTC clock */
+# define RCC_BDCR_RTCSEL_LSI (2 << RCC_BDCR_RTCSEL_SHIFT) /* 10: LSI oscillator clock used as RTC clock */
+# define RCC_BDCR_RTCSEL_HSE (3 << RCC_BDCR_RTCSEL_SHIFT) /* 11: HSE oscillator clock divided by 128 used as RTC clock */
+#define RCC_BDCR_RTCEN (1 << 15) /* Bit 15: RTC clock enable */
+#define RCC_BDCR_BDRST (1 << 16) /* Bit 16: Backup domain software reset */
+
+/* Control/status register */
+
+#define RCC_CSR_LSION (1 << 0) /* Bit 0: Internal Low Speed oscillator enable */
+#define RCC_CSR_LSIRDY (1 << 1) /* Bit 1: Internal Low Speed oscillator Ready */
+#define RCC_CSR_RMVF (1 << 24) /* Bit 24: Remove reset flag */
+#define RCC_CSR_BORRSTF (1 << 25) /* Bit 25: BOR reset flag */
+#define RCC_CSR_PINRSTF (1 << 26) /* Bit 26: PIN reset flag */
+#define RCC_CSR_PORRSTF (1 << 27) /* Bit 27: POR/PDR reset flag */
+#define RCC_CSR_SFTRSTF (1 << 28) /* Bit 28: Software Reset flag */
+#define RCC_CSR_IWDGRSTF (1 << 29) /* Bit 29: Independent Watchdog reset flag */
+#define RCC_CSR_WWDGRSTF (1 << 30) /* Bit 30: Window watchdog reset flag */
+#define RCC_CSR_LPWRRSTF (1 << 31) /* Bit 31: Low-Power reset flag */
+
+/* Spread spectrum clock generation register */
+
+#define RCC_SSCGR_MODPER_SHIFT (0) /* Bit 0-12: Modulation period */
+#define RCC_SSCGR_MODPER_MASK (0x1fff << RCC_SSCGR_MODPER_SHIFT)
+# define RCC_SSCGR_MODPER(n) ((n) << RCC_SSCGR_MODPER_SHIFT)
+#define RCC_SSCGR_INCSTEP_SHIFT (13) /* Bit 13-27: Incrementation step */
+#define RCC_SSCGR_INCSTEP_MASK (0x7fff << RCC_SSCGR_INCSTEP_SHIFT)
+# define RCC_SSCGR_INCSTEP(n) ((n) << RCC_SSCGR_INCSTEP_SHIFT)
+#define RCC_SSCGR_SPREADSEL (1 << 30) /* Bit 30: Spread Select */
+#define RCC_SSCGR_SSCGEN (1 << 31) /* Bit 31: Spread spectrum modulation enable */
+
+/* PLLI2S configuration register */
+
+#define RCC_PLLI2SCFGR_PLLI2SN_SHIFT (6) /* Bits 6-14: PLLI2S multiplication factor for VCO */
+#define RCC_PLLI2SCFGR_PLLI2SN_MASK (0x1ff << RCC_PLLI2SCFGR_PLLI2SN_SHIFT)
+#define RCC_PLLI2SCFGR_PLLI2SR_SHIFT (28) /* Bits 28-30: PLLI2S division factor for I2S clocks */
+#define RCC_PLLI2SCFGR_PLLI2SR_MASK (7 << RCC_PLLI2SCFGR_PLLI2SR_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RCC_H */
+
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h
new file mode 100644
index 000000000..fdfa9b323
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_rtc.h
@@ -0,0 +1,338 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f40xxx_rtc.h
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_CHIP_STM32F40XXX_RTC_H
+#define __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RTC_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_RTC_TR_OFFSET 0x0000 /* RTC time register */
+#define STM32_RTC_DR_OFFSET 0x0004 /* RTC date register */
+#define STM32_RTC_CR_OFFSET 0x0008 /* RTC control register */
+#define STM32_RTC_ISR_OFFSET 0x000c /* RTC initialization and status register */
+#define STM32_RTC_PRER_OFFSET 0x0010 /* RTC prescaler register */
+#define STM32_RTC_WUTR_OFFSET 0x0014 /* RTC wakeup timer register */
+#define STM32_RTC_CALIBR_OFFSET 0x0018 /* RTC calibration register */
+#define STM32_RTC_ALRMAR_OFFSET 0x001c /* RTC alarm A register */
+#define STM32_RTC_ALRMBR_OFFSET 0x0020 /* RTC alarm B register */
+#define STM32_RTC_WPR_OFFSET 0x0024 /* RTC write protection register */
+#define STM32_RTC_SSR_OFFSET 0x0028 /* RTC sub second register */
+#define STM32_RTC_SHIFTR_OFFSET 0x002c /* RTC shift control register */
+#define STM32_RTC_TSTR_OFFSET 0x0030 /* RTC time stamp time register */
+#define STM32_RTC_TSDR_OFFSET 0x0030 /* RTC time stamp date register */
+#define STM32_RTC_TSSSR_OFFSET 0x0038 /* RTC timestamp sub second register */
+#define STM32_RTC_CALR_OFFSET 0x003c /* RTC calibration register */
+#define STM32_RTC_TAFCR_OFFSET 0x0040 /* RTC tamper and alternate function configuration register */
+#define STM32_RTC_ALRMASSR_OFFSET 0x0044 /* RTC alarm A sub second register */
+#define STM32_RTC_ALRMBSSR_OFFSET 0x0048 /* RTC alarm B sub second register */
+
+#define STM32_RTC_BKR_OFFSET(n) (0x0050+((n)<<2))
+#define STM32_RTC_BK0R_OFFSET 0x0050 /* RTC backup register 0 */
+#define STM32_RTC_BK1R_OFFSET 0x0054 /* RTC backup register 1 */
+#define STM32_RTC_BK2R_OFFSET 0x0058 /* RTC backup register 2 */
+#define STM32_RTC_BK3R_OFFSET 0x005c /* RTC backup register 3 */
+#define STM32_RTC_BK4R_OFFSET 0x0060 /* RTC backup register 4 */
+#define STM32_RTC_BK5R_OFFSET 0x0064 /* RTC backup register 5 */
+#define STM32_RTC_BK6R_OFFSET 0x0068 /* RTC backup register 6 */
+#define STM32_RTC_BK7R_OFFSET 0x006c /* RTC backup register 7 */
+#define STM32_RTC_BK8R_OFFSET 0x0070 /* RTC backup register 8 */
+#define STM32_RTC_BK9R_OFFSET 0x0074 /* RTC backup register 9 */
+#define STM32_RTC_BK10R_OFFSET 0x0078 /* RTC backup register 10 */
+#define STM32_RTC_BK11R_OFFSET 0x007c /* RTC backup register 11 */
+#define STM32_RTC_BK12R_OFFSET 0x0080 /* RTC backup register 12 */
+#define STM32_RTC_BK13R_OFFSET 0x0084 /* RTC backup register 13 */
+#define STM32_RTC_BK14R_OFFSET 0x0088 /* RTC backup register 14 */
+#define STM32_RTC_BK15R_OFFSET 0x008c /* RTC backup register 15 */
+#define STM32_RTC_BK16R_OFFSET 0x0090 /* RTC backup register 16 */
+#define STM32_RTC_BK17R_OFFSET 0x0094 /* RTC backup register 17 */
+#define STM32_RTC_BK18R_OFFSET 0x0098 /* RTC backup register 18 */
+#define STM32_RTC_BK19R_OFFSET 0x009c /* RTC backup register 19 */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_RTC_TR (STM32_RTC_BASE+STM32_RTC_TR_OFFSET)
+#define STM32_RTC_DR (STM32_RTC_BASE+STM32_RTC_DR_OFFSET)
+#define STM32_RTC_CR (STM32_RTC_BASE+STM32_RTC_CR_OFFSET)
+#define STM32_RTC_ISR (STM32_RTC_BASE+STM32_RTC_ISR_OFFSET)
+#define STM32_RTC_PRER (STM32_RTC_BASE+STM32_RTC_PRER_OFFSET)
+#define STM32_RTC_WUTR (STM32_RTC_BASE+STM32_RTC_WUTR_OFFSET)
+#define STM32_RTC_CALIBR (STM32_RTC_BASE+STM32_RTC_CALIBR_OFFSET)
+#define STM32_RTC_ALRMAR (STM32_RTC_BASE+STM32_RTC_ALRMAR_OFFSET)
+#define STM32_RTC_ALRMBR (STM32_RTC_BASE+STM32_RTC_ALRMBR_OFFSET)
+#define STM32_RTC_WPR (STM32_RTC_BASE+STM32_RTC_WPR_OFFSET)
+#define STM32_RTC_SSR (STM32_RTC_BASE+STM32_RTC_SSR_OFFSET)
+#define STM32_RTC_SHIFTR (STM32_RTC_BASE+STM32_RTC_SHIFTR_OFFSET)
+#define STM32_RTC_TSTR (STM32_RTC_BASE+STM32_RTC_TSTR_OFFSET)
+#define STM32_RTC_TSDR (STM32_RTC_BASE+STM32_RTC_TSDR_OFFSET)
+#define STM32_RTC_TSSSR (STM32_RTC_BASE+STM32_RTC_TSSSR_OFFSET)
+#define STM32_RTC_CALR (STM32_RTC_BASE+STM32_RTC_CALR_OFFSET)
+#define STM32_RTC_TAFCR (STM32_RTC_BASE+STM32_RTC_TAFCR_OFFSET)
+#define STM32_RTC_ALRMASSR (STM32_RTC_BASE+STM32_RTC_ALRMASSR_OFFSET)
+#define STM32_RTC_ALRMBSSR (STM32_RTC_BASE+STM32_RTC_ALRMBSSR_OFFSET)
+
+#define STM32_RTC_BKR(n) (STM32_RTC_BASE+STM32_RTC_BKR_OFFSET(n))
+#define STM32_RTC_BK0R (STM32_RTC_BASE+STM32_RTC_BK0R_OFFSET)
+#define STM32_RTC_BK1R (STM32_RTC_BASE+STM32_RTC_BK1R_OFFSET)
+#define STM32_RTC_BK2R (STM32_RTC_BASE+STM32_RTC_BK2R_OFFSET)
+#define STM32_RTC_BK3R (STM32_RTC_BASE+STM32_RTC_BK3R_OFFSET)
+#define STM32_RTC_BK4R (STM32_RTC_BASE+STM32_RTC_BK4R_OFFSET)
+#define STM32_RTC_BK5R (STM32_RTC_BASE+STM32_RTC_BK5R_OFFSET)
+#define STM32_RTC_BK6R (STM32_RTC_BASE+STM32_RTC_BK6R_OFFSET)
+#define STM32_RTC_BK7R (STM32_RTC_BASE+STM32_RTC_BK7R_OFFSET)
+#define STM32_RTC_BK8R (STM32_RTC_BASE+STM32_RTC_BK8R_OFFSET)
+#define STM32_RTC_BK9R (STM32_RTC_BASE+STM32_RTC_BK9R_OFFSET)
+#define STM32_RTC_BK10R (STM32_RTC_BASE+STM32_RTC_BK10R_OFFSET)
+#define STM32_RTC_BK11R (STM32_RTC_BASE+STM32_RTC_BK11R_OFFSET)
+#define STM32_RTC_BK12R (STM32_RTC_BASE+STM32_RTC_BK12R_OFFSET)
+#define STM32_RTC_BK13R (STM32_RTC_BASE+STM32_RTC_BK13R_OFFSET)
+#define STM32_RTC_BK14R (STM32_RTC_BASE+STM32_RTC_BK14R_OFFSET)
+#define STM32_RTC_BK15R (STM32_RTC_BASE+STM32_RTC_BK15R_OFFSET)
+#define STM32_RTC_BK16R (STM32_RTC_BASE+STM32_RTC_BK16R_OFFSET)
+#define STM32_RTC_BK17R (STM32_RTC_BASE+STM32_RTC_BK17R_OFFSET)
+#define STM32_RTC_BK18R (STM32_RTC_BASE+STM32_RTC_BK18R_OFFSET)
+#define STM32_RTC_BK19R (STM32_RTC_BASE+STM32_RTC_BK19R_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+/* RTC time register */
+
+#define RTC_TR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format */
+#define RTC_TR_SU_MASK (15 << RTC_TR_SU_SHIFT)
+#define RTC_TR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format */
+#define RTC_TR_ST_MASK (7 << RTC_TR_ST_SHIFT)
+#define RTC_TR_MNU_SHIFT (8) /* Bit 8-11: Minute units in BCD format */
+#define RTC_TR_MNU_MASK (15 << RTC_TR_MNU_SHIFT)
+#define RTC_TR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format */
+#define RTC_TR_MNT_MASK (7 << RTC_TR_MNT_SHIFT)
+#define RTC_TR_HU_SHIFT (16) /* Bit 16-19: Hour units in BCD format */
+#define RTC_TR_HU_MASK (15 << RTC_TR_HU_SHIFT)
+#define RTC_TR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format */
+#define RTC_TR_HT_MASK (3 << RTC_TR_HT_SHIFT)
+#define RTC_TR_PM (1 << 22) /* Bit 22: AM/PM notation */
+#define RTC_TR_RESERVED_BITS (0xff808080)
+
+/* RTC date register */
+
+#define RTC_DR_DU_SHIFT (0) /* Bits 0-3: Date units in BCD format */
+#define RTC_DR_DU_MASK (15 << RTC_DR_DU_SHIFT)
+#define RTC_DR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */
+#define RTC_DR_DT_MASK (3 << RTC_DR_DT_SHIFT)
+#define RTC_DR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */
+#define RTC_DR_MU_MASK (15 << RTC_DR_MU_SHIFT)
+#define RTC_DR_MT (1 << 12) /* Bit 12: Month tens in BCD format */
+#define RTC_DR_WDU_SHIFT (13) /* Bits 13-15: Week day units */
+#define RTC_DR_WDU_MASK (7 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_MONDAY (1 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_TUESDAY (2 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_WEDNESDAY (3 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_THURSDAY (4 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_FRIDAY (5 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_SATURDAY (6 << RTC_DR_WDU_SHIFT)
+# define RTC_DR_WDU_SUNDAY (7 << RTC_DR_WDU_SHIFT)
+#define RTC_DR_YU_SHIFT (16) /* Bits 16-19: Year units in BCD format */
+#define RTC_DR_YU_MASK (15 << RTC_DR_YU_SHIFT)
+#define RTC_DR_YT_SHIFT (20) /* Bits 20-23: Year tens in BCD format */
+#define RTC_DR_YT_MASK (15 << RTC_DR_YT_SHIFT)
+#define RTC_DR_RESERVED_BITS (0xff0000c0)
+
+/* RTC control register */
+
+#define RTC_CR_WUCKSEL_SHIFT (0) /* Bits 0-2: Wakeup clock selection */
+#define RTC_CR_WUCKSEL_MASK (7 << RTC_CR_WUCKSEL_SHIFT)
+# define RTC_CR_WUCKSEL_RTCDIV16 (0 << RTC_CR_WUCKSEL_SHIFT) /* 000: RTC/16 clock is selected */
+# define RTC_CR_WUCKSEL_RTCDIV8 (1 << RTC_CR_WUCKSEL_SHIFT) /* 001: RTC/8 clock is selected */
+# define RTC_CR_WUCKSEL_RTCDIV4 (2 << RTC_CR_WUCKSEL_SHIFT) /* 010: RTC/4 clock is selected */
+# define RTC_CR_WUCKSEL_RTCDIV2 (3 << RTC_CR_WUCKSEL_SHIFT) /* 011: RTC/2 clock is selected */
+# define RTC_CR_WUCKSEL_CKSPRE (4 << RTC_CR_WUCKSEL_SHIFT) /* 10x: ck_spre clock is selected */
+# define RTC_CR_WUCKSEL_CKSPREADD (6 << RTC_CR_WUCKSEL_SHIFT) /* 11x: ck_spr clock and 216 added WUT counter */
+#define RTC_CR_TSEDGE (1 << 3) /* Bit 3: Timestamp event active edge */
+#define RTC_CR_REFCKON (1 << 4) /* Bit 4: Reference clock detection enable (50 or 60 Hz) */
+#define RTC_CR_BYPSHAD (1 << 5) /* Bit 5: Bypass the shadow registers */
+#define RTC_CR_FMT (1 << 6) /* Bit 6: Hour format */
+#define RTC_CR_DCE (1 << 7) /* Bit 7: Coarse digital calibration enable */
+#define RTC_CR_ALRAE (1 << 8) /* Bit 8: Alarm A enable */
+#define RTC_CR_ALRBE (1 << 9) /* Bit 9: Alarm B enable */
+#define RTC_CR_WUTE (1 << 10) /* Bit 10: Wakeup timer enable */
+#define RTC_CR_TSE (1 << 11) /* Bit 11: Time stamp enable */
+#define RTC_CR_ALRAIE (1 << 12) /* Bit 12: Alarm A interrupt enable */
+#define RTC_CR_ALRBIE (1 << 13) /* Bit 13: Alarm B interrupt enable */
+#define RTC_CR_WUTIE (1 << 14) /* Bit 14: Wakeup timer interrupt enable */
+#define RTC_CR_TSIE (1 << 15) /* Bit 15: Timestamp interrupt enable */
+#define RTC_CR_ADD1H (1 << 16) /* Bit 16: Add 1 hour (summer time change) */
+#define RTC_CR_SUB1H (1 << 17) /* Bit 17: Subtract 1 hour (winter time change) */
+#define RTC_CR_BKP (1 << 18) /* Bit 18: Backup */
+#define RTC_CR_COSEL (1 << 19) /* Bit 19 : Calibration output selection */
+#define RTC_CR_POL (1 << 20) /* Bit 20: Output polarity */
+#define RTC_CR_OSEL_SHIFT (21) /* Bits 21-22: Output selection */
+#define RTC_CR_OSEL_MASK (3 << RTC_CR_OSEL_SHIFT)
+# define RTC_CR_OSEL_DISABLED (0 << RTC_CR_OSEL_SHIFT) /* 00: Output disabled */
+# define RTC_CR_OSEL_ALRMA (1 << RTC_CR_OSEL_SHIFT) /* 01: Alarm A output enabled */
+# define RTC_CR_OSEL_ALRMB (2 << RTC_CR_OSEL_SHIFT) /* 10: Alarm B output enabled */
+# define RTC_CR_OSEL_WUT (3 << RTC_CR_OSEL_SHIFT) /* 11: Wakeup output enabled */
+#define RTC_CR_COE (1 << 23) /* Bit 23: Calibration output enable */
+
+/* RTC initialization and status register */
+
+#define RTC_ISR_ALRAWF (1 << 0) /* Bit 0: Alarm A write flag */
+#define RTC_ISR_ALRBWF (1 << 1) /* Bit 1: Alarm B write flag */
+#define RTC_ISR_WUTWF (1 << 2) /* Bit 2: Wakeup timer write flag */
+#define RTC_ISR_SHPF (1 << 3) /* Bit 3: Shift operation pending */
+#define RTC_ISR_INITS (1 << 4) /* Bit 4: Initialization status flag */
+#define RTC_ISR_RSF (1 << 5) /* Bit 5: Registers synchronization flag */
+#define RTC_ISR_INITF (1 << 6) /* Bit 6: Initialization flag */
+#define RTC_ISR_INIT (1 << 7) /* Bit 7: Initialization mode */
+#define RTC_ISR_ALRAF (1 << 8) /* Bit 8: Alarm A flag */
+#define RTC_ISR_ALRBF (1 << 9) /* Bit 9: Alarm B flag */
+#define RTC_ISR_WUTF (1 << 10) /* Bit 10: Wakeup timer flag */
+#define RTC_ISR_TSF (1 << 11) /* Bit 11: Timestamp flag */
+#define RTC_ISR_TSOVF (1 << 12) /* Bit 12: Timestamp overflow flag */
+#define RTC_ISR_TAMP1F (1 << 13) /* Bit 13: Tamper detection flag */
+#define RTC_ISR_TAMP2F (1 << 14) /* Bit 14: TAMPER2 detection flag */
+#define RTC_ISR_RECALPF (1 << 16) /* Bit 16: Recalibration pending Flag */
+#define RTC_ISR_ALLFLAGS (0x00017fff)
+
+/* RTC prescaler register */
+
+#define RTC_PRER_PREDIV_S_SHIFT (0) /* Bits 0-14: Synchronous prescaler factor */
+#define RTC_PRER_PREDIV_S_MASK (0x7fff << RTC_PRER_PREDIV_S_SHIFT)
+#define RTC_PRER_PREDIV_A_SHIFT (16) /* Bits 16-22: Asynchronous prescaler factor */
+#define RTC_PRER_PREDIV_A_MASK (0x7f << RTC_PRER_PREDIV_A_SHIFT)
+
+/* RTC wakeup timer register */
+
+#define RTC_WUTR_MASK (0xffff) /* Bits 15:0 Wakeup auto-reload value bits */
+
+/* RTC calibration register */
+
+#define RTC_CALIBR_DCS (1 << 7) /* Bit 7 Digital calibration sign */
+#define RTC_CALIBR_DC_SHIFT (0) /* Bits 4:0 0-4: Digital calibration */
+#define RTC_CALIBR_DC_MASK (31 << RTC_CALIBR_DC_SHIFT)
+# define RTC_CALIBR_DC(n) (((n) >> 2) << RTC_CALIBR_DC_SHIFT) /* n= 0, 4, 8, ... 126 */
+
+/* RTC alarm A/B registers */
+
+#define RTC_ALRMR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format. */
+#define RTC_ALRMR_SU_MASK (15 << RTC_ALRMR_SU_SHIFT)
+#define RTC_ALRMR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format. */
+#define RTC_ALRMR_ST_MASK (7 << RTC_ALRMR_ST_SHIFT)
+#define RTC_ALRMR_MSK1 (1 << 7) /* Bit 7 : Alarm A seconds mask */
+#define RTC_ALRMR_MNU_SHIFT (8) /* Bits 8-11: Minute units in BCD format. */
+#define RTC_ALRMR_MNU_MASK (15 << RTC_ALRMR_MNU_SHIFT)
+#define RTC_ALRMR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format. */
+#define RTC_ALRMR_MNT_MASK (7 << RTC_ALRMR_MNT_SHIFT)
+#define RTC_ALRMR_MSK2 (1 << 15) /* Bit 15 : Alarm A minutes mask */
+#define RTC_ALRMR_HU_SHIFT (16) /* Bits 16-19: Hour units in BCD format. */
+#define RTC_ALRMR_HU_MASK (15 << RTC_ALRMR_HU_SHIFT)
+#define RTC_ALRMR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format. */
+#define RTC_ALRMR_HT_MASK (3 << RTC_ALRMR_HT_SHIFT)
+#define RTC_ALRMR_PM (1 << 22) /* Bit 22 : AM/PM notation */
+#define RTC_ALRMR_MSK3 (1 << 23) /* Bit 23 : Alarm A hours mask */
+#define RTC_ALRMR_DU_SHIFT (24) /* Bits 24-27: Date units or day in BCD format. */
+#define RTC_ALRMR_DU_MASK (15 << RTC_ALRMR_DU_SHIFT)
+#define RTC_ALRMR_DT_SHIFT (28) /* Bits 28-29: Date tens in BCD format. */
+#define RTC_ALRMR_DT_MASK (3 << RTC_ALRMR_DT_SHIFT)
+#define RTC_ALRMR_WDSEL (1 << 30) /* Bit 30: Week day selection */
+#define RTC_ALRMR_MSK4 (1 << 31) /* Bit 31: Alarm A date mask */
+
+/* RTC write protection register */
+
+#define RTC_WPR_MASK (0xff) /* Bits 0-7: Write protection key */
+
+/* RTC sub second register */
+
+#define RTC_SSR_MASK (0xffff) /* Bits 0-15: Sub second value */
+
+/* RTC shift control register */
+
+#define RTC_SHIFTR_SUBFS_SHIFT (0) /* Bits 0-14: Subtract a fraction of a second */
+#define RTC_SHIFTR_SUBFS_MASK (0x7ffff << RTC_SHIFTR_SUBFS_SHIFT)
+#define RTC_SHIFTR_ADD1S (1 << 31) /* Bit 31: Add one second */
+
+/* RTC time stamp time register */
+
+#define RTC_TSTR_SU_SHIFT (0) /* Bits 0-3: Second units in BCD format. */
+#define RTC_TSTR_SU_MASK (15 << RTC_TSTR_SU_SHIFT)
+#define RTC_TSTR_ST_SHIFT (4) /* Bits 4-6: Second tens in BCD format. */
+#define RTC_TSTR_ST_MASK (7 << RTC_TSTR_ST_SHIFT)
+#define RTC_TSTR_MNU_SHIFT (8) /* Bits 8-11: Minute units in BCD format. */
+#define RTC_TSTR_MNU_MASK (15 << RTC_TSTR_MNU_SHIFT)
+#define RTC_TSTR_MNT_SHIFT (12) /* Bits 12-14: Minute tens in BCD format. */
+#define RTC_TSTR_MNT_MASK (7 << RTC_TSTR_MNT_SHIFT)
+#define RTC_TSTR_HU_SHIFT (16) /* Bits 16-19: Hour units in BCD format. */
+#define RTC_TSTR_HU_MASK (15 << RTC_TSTR_HU_SHIFT)
+#define RTC_TSTR_HT_SHIFT (20) /* Bits 20-21: Hour tens in BCD format. */
+#define RTC_TSTR_HT_MASK (3 << RTC_TSTR_HT_SHIFT)
+#define RTC_TSTR_PM (1 << 22) /* Bit 22: AM/PM notation */
+
+/* RTC time stamp date register */
+
+#define RTC_TSDR_DU_SHIFT (0) /* Bit 0-3: Date units in BCD format */
+#define RTC_TSDR_DU_MASK (15 << RTC_TSDR_DU_SHIFT) */
+#define RTC_TSDR_DT_SHIFT (4) /* Bits 4-5: Date tens in BCD format */
+#define RTC_TSDR_DT_MASK (3 << RTC_TSDR_DT_SHIFT)
+#define RTC_TSDR_MU_SHIFT (8) /* Bits 8-11: Month units in BCD format */
+#define RTC_TSDR_MU_MASK (xx << RTC_TSDR_MU_SHIFT)
+#define RTC_TSDR_MT (1 << 12) /* Bit 12: Month tens in BCD format */
+#define RTC_TSDR_WDU_SHIFT (13) /* Bits 13-15: Week day units */
+#define RTC_TSDR_WDU_MASK (7 << RTC_TSDR_WDU_SHIFT)
+
+/* RTC timestamp sub second register */
+
+#define RTC_TSSSR_MASK (0xffff) /* Bits 0-15: Sub second value */
+
+/* RTC calibration register */
+
+#define RTC_CALR_
+
+/* RTC tamper and alternate function configuration register */
+
+#define RTC_TAFCR_CALM_SHIFT (0) /* Bits 0-8: Calibration minus */
+#define RTC_TAFCR_CALM_MASK (0x1ff << RTC_TAFCR_CALM_SHIFT)
+#define RTC_TAFCR_CALW16 (1 << 13) /* Bit 13: Use a 16-second calibration cycle period */
+#define RTC_TAFCR_CALW8 (1 << 14) /* Bit 14: Use an 8-second calibration cycle period */
+#define RTC_TAFCR_CALP (1 << 15) /* Bit 15: Increase frequency of RTC by 488.5 ppm */
+
+/* RTC alarm A/B sub second register */
+
+#define RTC_ALRMSSR_SS_SHIFT (0) /* Bits 0-15: Sub second value */
+#define RTC_ALRMSSR_SS_MASK (0xffff << RTC_ALRMSSR_SS_SHIFT)
+#define RTC_ALRMSSR_MASKSS_SHIFT (0) /* Bits 24-27: Mask the most-significant bits starting at this bit */
+#define RTC_ALRMSSR_MASKSS_MASK (0xffff << RTC_ALRMSSR_SS_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F40XXX_RTC_H */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_vectors.h b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_vectors.h
new file mode 100644
index 000000000..8db1bd19e
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/chip/stm32f40xxx_vectors.h
@@ -0,0 +1,142 @@
+/************************************************************************************
+ * arch/arm/src/stm32/chip/stm32f40xxx_vectors.h
+ *
+ * Copyright (C) 2011-2012 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.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ * Pre-processor definitions
+ ************************************************************************************/
+
+/* This file is included by stm32_vectors.S. It provides the macro VECTOR that
+ * supplies ach STM32F40xxx vector in terms of a (lower-case) ISR label and an
+ * (upper-case) IRQ number as defined in arch/arm/include/stm32/stm32f40xxx_irq.h.
+ * stm32_vectors.S will defined the VECTOR in different ways in order to generate
+ * the interrupt vectors and handlers in their final form.
+ */
+
+/* If the common ARMv7-M vector handling is used, then all it needs is the following
+ * definition that provides the number of supported vectors.
+ */
+
+#ifdef CONFIG_ARMV7M_CMNVECTOR
+
+/* Reserve 82 interrupt table entries for I/O interrupts. */
+
+# define ARMV7M_PERIPHERAL_INTERRUPTS 82
+
+#else
+
+VECTOR(stm32_wwdg, STM32_IRQ_WWDG) /* Vector 16+0: Window Watchdog interrupt */
+VECTOR(stm32_pvd, STM32_IRQ_PVD) /* Vector 16+1: PVD through EXTI Line detection interrupt */
+VECTOR(stm32_tamper, STM32_IRQ_TAMPER) /* Vector 16+2: Tamper and time stamp interrupts */
+VECTOR(stm32_rtc_wkup, STM32_IRQ_RTC_WKUP) /* Vector 16+3: RTC global interrupt */
+VECTOR(stm32_flash, STM32_IRQ_FLASH) /* Vector 16+4: Flash global interrupt */
+VECTOR(stm32_rcc, STM32_IRQ_RCC) /* Vector 16+5: RCC global interrupt */
+VECTOR(stm32_exti0, STM32_IRQ_EXTI0) /* Vector 16+6: EXTI Line 0 interrupt */
+VECTOR(stm32_exti1, STM32_IRQ_EXTI1) /* Vector 16+7: EXTI Line 1 interrupt */
+VECTOR(stm32_exti2, STM32_IRQ_EXTI2) /* Vector 16+8: EXTI Line 2 interrupt */
+VECTOR(stm32_exti3, STM32_IRQ_EXTI3) /* Vector 16+9: EXTI Line 3 interrupt */
+VECTOR(stm32_exti4, STM32_IRQ_EXTI4) /* Vector 16+10: EXTI Line 4 interrupt */
+VECTOR(stm32_dma1s0, STM32_IRQ_DMA1S0) /* Vector 16+11: DMA1 Stream 0 global interrupt */
+VECTOR(stm32_dma1s1, STM32_IRQ_DMA1S1) /* Vector 16+12: DMA1 Stream 1 global interrupt */
+VECTOR(stm32_dma1s2, STM32_IRQ_DMA1S2) /* Vector 16+13: DMA1 Stream 2 global interrupt */
+VECTOR(stm32_dma1s3, STM32_IRQ_DMA1S3) /* Vector 16+14: DMA1 Stream 3 global interrupt */
+VECTOR(stm32_dma1s4, STM32_IRQ_DMA1S4) /* Vector 16+15: DMA1 Stream 4 global interrupt */
+VECTOR(stm32_dma1s5, STM32_IRQ_DMA1S5) /* Vector 16+16: DMA1 Stream 5 global interrupt */
+VECTOR(stm32_dma1s6, STM32_IRQ_DMA1S6) /* Vector 16+17: DMA1 Stream 6 global interrupt */
+VECTOR(stm32_adc, STM32_IRQ_ADC) /* Vector 16+18: ADC1, ADC2, and ADC3 global interrupt */
+VECTOR(stm32_can1tx, STM32_IRQ_CAN1TX) /* Vector 16+19: CAN1 TX interrupts */
+VECTOR(stm32_can1rx0, STM32_IRQ_CAN1RX0) /* Vector 16+20: CAN1 RX0 interrupts */
+VECTOR(stm32_can1rx1, STM32_IRQ_CAN1RX1) /* Vector 16+21: CAN1 RX1 interrupt */
+VECTOR(stm32_can1sce, STM32_IRQ_CAN1SCE) /* Vector 16+22: CAN1 SCE interrupt */
+VECTOR(stm32_exti95, STM32_IRQ_EXTI95) /* Vector 16+23: EXTI Line[9:5] interrupts */
+VECTOR(stm32_tim1brk, STM32_IRQ_TIM1BRK) /* Vector 16+24: TIM1 Break interrupt/TIM9 global interrupt */
+VECTOR(stm32_tim1up, STM32_IRQ_TIM1UP) /* Vector 16+25: TIM1 Update interrupt/TIM10 global interrupt */
+VECTOR(stm32_tim1trgcom, STM32_IRQ_TIM1TRGCOM) /* Vector 16+26: TIM1 Trigger and Commutation interrupts/TIM11 global interrupt */
+VECTOR(stm32_tim1cc, STM32_IRQ_TIM1CC) /* Vector 16+27: TIM1 Capture Compare interrupt */
+VECTOR(stm32_tim2, STM32_IRQ_TIM2) /* Vector 16+28: TIM2 global interrupt */
+VECTOR(stm32_tim3, STM32_IRQ_TIM3) /* Vector 16+29: TIM3 global interrupt */
+VECTOR(stm32_tim4, STM32_IRQ_TIM4) /* Vector 16+30: TIM4 global interrupt */
+VECTOR(stm32_i2c1ev, STM32_IRQ_I2C1EV) /* Vector 16+31: I2C1 event interrupt */
+VECTOR(stm32_i2c1er, STM32_IRQ_I2C1ER) /* Vector 16+32: I2C1 error interrupt */
+VECTOR(stm32_i2c2ev, STM32_IRQ_I2C2EV) /* Vector 16+33: I2C2 event interrupt */
+VECTOR(stm32_i2c2er, STM32_IRQ_I2C2ER) /* Vector 16+34: I2C2 error interrupt */
+VECTOR(stm32_spi1, STM32_IRQ_SPI1) /* Vector 16+35: SPI1 global interrupt */
+VECTOR(stm32_spi2, STM32_IRQ_SPI2) /* Vector 16+36: SPI2 global interrupt */
+VECTOR(stm32_usart1, STM32_IRQ_USART1) /* Vector 16+37: USART1 global interrupt */
+VECTOR(stm32_usart2, STM32_IRQ_USART2) /* Vector 16+38: USART2 global interrupt */
+VECTOR(stm32_usart3, STM32_IRQ_USART3) /* Vector 16+39: USART3 global interrupt */
+VECTOR(stm32_exti1510, STM32_IRQ_EXTI1510) /* Vector 16+40: EXTI Line[15:10] interrupts */
+VECTOR(stm32_rtcalrm, STM32_IRQ_RTCALRM) /* Vector 16+41: RTC alarm through EXTI line interrupt */
+VECTOR(stm32_otgfswkup, STM32_IRQ_OTGFSWKUP) /* Vector 16+42: USB On-The-Go FS Wakeup through EXTI line interrupt */
+VECTOR(stm32_tim8brk, STM32_IRQ_TIM8BRK) /* Vector 16+43: TIM8 Break interrupt/TIM12 global interrupt */
+VECTOR(stm32_tim8up, STM32_IRQ_TIM8UP) /* Vector 16+44: TIM8 Update interrup/TIM13 global interrupt */
+VECTOR(stm32_tim8trgcom, STM32_IRQ_TIM8TRGCOM) /* Vector 16+45: TIM8 Trigger and Commutation interrupts/TIM14 global interrupt */
+VECTOR(stm32_tim8cc, STM32_IRQ_TIM8CC) /* Vector 16+46: TIM8 Capture Compare interrupt */
+VECTOR(stm32_dma1s7, STM32_IRQ_DMA1S7) /* Vector 16+47: DMA1 Stream 7 global interrupt */
+VECTOR(stm32_fsmc, STM32_IRQ_FSMC) /* Vector 16+48: FSMC global interrupt */
+VECTOR(stm32_sdio, STM32_IRQ_SDIO) /* Vector 16+49: SDIO global interrupt */
+VECTOR(stm32_tim5, STM32_IRQ_TIM5) /* Vector 16+50: TIM5 global interrupt */
+VECTOR(stm32_spi3, STM32_IRQ_SPI3) /* Vector 16+51: SPI3 global interrupt */
+VECTOR(stm32_uart4, STM32_IRQ_UART4) /* Vector 16+52: UART4 global interrupt */
+VECTOR(stm32_uart5, STM32_IRQ_UART5) /* Vector 16+53: UART5 global interrupt */
+VECTOR(stm32_tim6, STM32_IRQ_TIM6) /* Vector 16+54: TIM6 global interrupt/DAC1 and DAC2 underrun error interrupts */
+VECTOR(stm32_tim7, STM32_IRQ_TIM7) /* Vector 16+55: TIM7 global interrupt */
+VECTOR(stm32_dma2s0, STM32_IRQ_DMA2S0) /* Vector 16+56: DMA2 Stream 0 global interrupt */
+VECTOR(stm32_dma2s1, STM32_IRQ_DMA2S1) /* Vector 16+57: DMA2 Stream 1 global interrupt */
+VECTOR(stm32_dma2s2, STM32_IRQ_DMA2S2) /* Vector 16+58: DMA2 Stream 2 global interrupt */
+VECTOR(stm32_dma2s3, STM32_IRQ_DMA2S3) /* Vector 16+59: DMA2 Stream 3 global interrupt */
+VECTOR(stm32_dma2s4, STM32_IRQ_DMA2S4) /* Vector 16+60: DMA2 Stream 4 global interrupt */
+VECTOR(stm32_eth, STM32_IRQ_ETH) /* Vector 16+61: Ethernet global interrupt */
+VECTOR(stm32_ethwkup, STM32_IRQ_ETHWKUP) /* Vector 16+62: Ethernet Wakeup through EXTI line interrupt */
+VECTOR(stm32_can2tx, STM32_IRQ_CAN2TX) /* Vector 16+63: CAN2 TX interrupts */
+VECTOR(stm32_can2rx0, STM32_IRQ_CAN2RX0) /* Vector 16+64: CAN2 RX0 interrupts */
+VECTOR(stm32_can2rx1, STM32_IRQ_CAN2RX1) /* Vector 16+65: CAN2 RX1 interrupt */
+VECTOR(stm32_can2sce, STM32_IRQ_CAN2SCE) /* Vector 16+66: CAN2 SCE interrupt */
+VECTOR(stm32_otgfs, STM32_IRQ_OTGFS) /* Vector 16+67: USB On The Go FS global interrupt */
+VECTOR(stm32_dma2s5, STM32_IRQ_DMA2S5) /* Vector 16+68: DMA2 Stream 5 global interrupt */
+VECTOR(stm32_dma2s6, STM32_IRQ_DMA2S6) /* Vector 16+69: DMA2 Stream 6 global interrupt */
+VECTOR(stm32_dma2s7, STM32_IRQ_DMA2S7) /* Vector 16+70: DMA2 Stream 7 global interrupt */
+VECTOR(stm32_usart6, STM32_IRQ_USART6) /* Vector 16+71: USART6 global interrupt */
+VECTOR(stm32_i2c3ev, STM32_IRQ_I2C3EV) /* Vector 16+72: I2C3 event interrupt */
+VECTOR(stm32_i2c3er, STM32_IRQ_I2C3ER) /* Vector 16+73: I2C3 error interrupt */
+VECTOR(stm32_otghsep1out, STM32_IRQ_OTGHSEP1OUT) /* Vector 16+74: USB On The Go HS End Point 1 Out global interrupt */
+VECTOR(stm32_otghsep1in, STM32_IRQ_OTGHSEP1IN) /* Vector 16+75: USB On The Go HS End Point 1 In global interrupt */
+VECTOR(stm32_otghswkup, STM32_IRQ_OTGHSWKUP) /* Vector 16+76: USB On The Go HS Wakeup through EXTI interrupt */
+VECTOR(stm32_otghs, STM32_IRQ_OTGHS ) /* Vector 16+77: USB On The Go HS global interrupt */
+VECTOR(stm32_dcmi, STM32_IRQ_DCMI) /* Vector 16+78: DCMI global interrupt */
+VECTOR(stm32_cryp, STM32_IRQ_CRYP) /* Vector 16+79: CRYP crypto global interrupt */
+VECTOR(stm32_hash, STM32_IRQ_HASH) /* Vector 16+80: Hash and Rng global interrupt */
+VECTOR(stm32_fpu, STM32_IRQ_FPU) /* Vector 16+81: FPU global interrupt */
+
+#endif /* CONFIG_ARMV7M_CMNVECTOR */
diff --git a/nuttx/arch/arm/src/stm32/stm32.h b/nuttx/arch/arm/src/stm32/stm32.h
new file mode 100644
index 000000000..44a23aece
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32.h
@@ -0,0 +1,103 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32.h
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Authors: Uros Platise <uros.platise@isotel.eu>
+ * 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_STM32_STM32_H
+#define __ARCH_ARM_SRC_STM32_STM32_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "up_internal.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Additional Configuration *********************************************************/
+/* Custom debug settings used in the STM32 port. These are managed by STM32-specific
+ * logic and not the common logic in include/debug.h. NOTE: Some of these also
+ * depend on CONFIG_DEBUG_VERBOSE
+ */
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_DEBUG_DMA
+# undef CONFIG_DEBUG_RTC
+# undef CONFIG_DEBUG_I2C
+# undef CONFIG_DEBUG_CAN
+# undef CONFIG_DEBUG_PWM
+# undef CONFIG_DEBUG_QENCODER
+#endif
+
+/* NVIC priority levels *************************************************************/
+
+#define NVIC_SYSH_PRIORITY_MIN 0xff /* All bits set in minimum priority */
+#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */
+#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */
+
+/* Peripherals **********************************************************************/
+
+#include "chip.h"
+#include "stm32_adc.h"
+//#include "stm32_bkp.h"
+#include "stm32_can.h"
+#include "stm32_dbgmcu.h"
+#include "stm32_dma.h"
+#include "stm32_exti.h"
+#include "stm32_flash.h"
+#include "stm32_fsmc.h"
+#include "stm32_gpio.h"
+#include "stm32_i2c.h"
+#include "stm32_pwr.h"
+#include "stm32_rcc.h"
+#include "stm32_rtc.h"
+#include "stm32_sdio.h"
+#include "stm32_spi.h"
+#include "stm32_tim.h"
+#include "stm32_uart.h"
+#include "stm32_usbdev.h"
+#include "stm32_wdg.h"
+#include "stm32_lowputc.h"
+#include "stm32_eth.h"
+
+#endif /* __ARCH_ARM_SRC_STM32_STM32_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_adc.c b/nuttx/arch/arm/src/stm32/stm32_adc.c
new file mode 100644
index 000000000..a45b732ae
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_adc.c
@@ -0,0 +1,1780 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_adc.c
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ * Diego Sanchez <dsanchez@nx-engineering.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <unistd.h>
+
+#include <arch/board/board.h>
+#include <nuttx/arch.h>
+#include <nuttx/analog/adc.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "chip.h"
+#include "stm32_internal.h"
+#include "stm32_adc.h"
+
+#ifdef CONFIG_ADC
+#if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* ADC interrupts ***********************************************************/
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ADC_SR_ALLINTS (ADC_SR_AWD | ADC_SR_EOC | ADC_SR_JEOC)
+#else
+# define ADC_SR_ALLINTS (ADC_SR_AWD | ADC_SR_EOC | ADC_SR_JEOC | ADC_SR_OVR)
+#endif
+
+#ifdef CONFIG_STM32_STM32F10XX
+# define ADC_CR1_ALLINTS (ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_JEOCIE)
+#else
+# define ADC_CR1_ALLINTS (ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_JEOCIE | ADC_CR1_OVRIE)
+#endif
+
+/* The maximum number of channels that can be sampled. If dma support is
+ * not enabled, then only a single channel can be sampled. Otherwise,
+ * data overruns would occur.
+ */
+
+#ifdef CONFIG_ADC_DMA
+# define ADC_MAX_SAMPLES 16
+#else
+# define ADC_MAX_SAMPLES 1
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure describes the state of one ADC block */
+
+struct stm32_dev_s
+{
+ uint8_t irq; /* Interrupt generated by this ADC block */
+ uint8_t nchannels; /* Number of channels */
+ uint8_t intf; /* ADC interface number */
+ uint8_t current; /* Current ADC channel being converted */
+#ifdef ADC_HAVE_TIMER
+ uint8_t trigger; /* Timer trigger channel: 0=CC1, 1=CC2, 2=CC3, 3=CC4, 4=TRGO */
+#endif
+ xcpt_t isr; /* Interrupt handler for this ADC block */
+ uint32_t base; /* Base address of registers unique to this ADC block */
+#ifdef ADC_HAVE_TIMER
+ uint32_t tbase; /* Base address of timer used by this ADC block */
+ uint32_t extsel; /* EXTSEL value used by this ADC block */
+ uint32_t pclck; /* The PCLK frequency that drives this timer */
+ uint32_t freq; /* The desired frequency of conversions */
+#endif
+ uint8_t chanlist[ADC_MAX_SAMPLES];
+#ifdef CONFIG_ADC_DMA
+ const unsigned int rxdma_channel; /* DMA channel assigned */
+ DMA_HANDLE rxdma; /* currently-open receive DMA stream */
+ bool rxenable; /* DMA-based reception en/disable */
+ uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
+ int32_t *const rxfifo; /* Receive DMA buffer */
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+# ifdef CONFIG_ADC_DMA
+static int16_t g_adc3dmarxfifo[ADC_MAX_SAMPLES];
+# endif
+
+
+
+/* ADC Register access */
+
+static uint32_t adc_getreg(struct stm32_dev_s *priv, int offset);
+static void adc_putreg(struct stm32_dev_s *priv, int offset, uint32_t value);
+#ifdef ADC_HAVE_TIMER
+static uint16_t tim_getreg(struct stm32_dev_s *priv, int offset);
+static void tim_putreg(struct stm32_dev_s *priv, int offset, uint16_t value);
+static void adc_tim_dumpregs(struct stm32_dev_s *priv, FAR const char *msg);
+#endif
+static void adc_rccreset(struct stm32_dev_s *priv, bool reset);
+
+/* ADC Interrupt Handler */
+
+static int adc_interrupt(FAR struct adc_dev_s *dev);
+#if defined(CONFIG_STM32_STM32F10XX) && (defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2))
+static int adc12_interrupt(int irq, void *context);
+#endif
+#if defined(CONFIG_STM32_STM32F10XX) && defined (CONFIG_STM32_ADC3)
+static int adc3_interrupt(int irq, void *context);
+#endif
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+static int adc123_interrupt(int irq, void *context);
+#endif
+
+/* ADC Driver Methods */
+
+static void adc_reset(FAR struct adc_dev_s *dev);
+static int adc_setup(FAR struct adc_dev_s *dev);
+static void adc_shutdown(FAR struct adc_dev_s *dev);
+static void adc_rxint(FAR struct adc_dev_s *dev, bool enable);
+static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg);
+static void adc_enable(FAR struct stm32_dev_s *priv, bool enable);
+
+#ifdef ADC_HAVE_TIMER
+static void adc_timstart(FAR struct stm32_dev_s *priv, bool enable);
+static int adc_timinit(FAR struct stm32_dev_s *priv);
+#endif
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable);
+#endif
+
+#ifdef CONFIG_ADC_DMA
+static int up_dma_setup(struct adc_dev_s *dev);
+static void up_dma_shutdown(struct adc_dev_s *dev);
+//static int up_dma_receive(struct uart_dev_s *dev, uint32_t *status);
+//static void up_dma_rxint(struct uart_dev_s *dev, bool enable);
+//static bool up_dma_rxavailable(struct uart_dev_s *dev);
+static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, FAR struct adc_dev_s *dev);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* ADC interface operations */
+
+static const struct adc_ops_s g_adcops =
+{
+ .ao_reset = adc_reset,
+ .ao_setup = adc_setup,
+ .ao_shutdown = adc_shutdown,
+ .ao_rxint = adc_rxint,
+ .ao_ioctl = adc_ioctl,
+};
+
+/* ADC1 state */
+
+#ifdef CONFIG_STM32_ADC1
+static struct stm32_dev_s g_adcpriv1 =
+{
+#ifdef CONFIG_STM32_STM32F10XX
+ .irq = STM32_IRQ_ADC12,
+ .isr = adc12_interrupt,
+#else
+ .irq = STM32_IRQ_ADC,
+ .isr = adc123_interrupt,
+#endif
+ .intf = 1,
+ .base = STM32_ADC1_BASE,
+#ifdef ADC1_HAVE_TIMER
+ .trigger = CONFIG_STM32_ADC1_TIMTRIG,
+ .tbase = ADC1_TIMER_BASE,
+ .extsel = ADC1_EXTSEL_VALUE,
+ .pclck = ADC1_TIMER_PCLK_FREQUENCY,
+ .freq = CONFIG_STM32_ADC1_SAMPLE_FREQUENCY,
+#endif
+};
+
+static struct adc_dev_s g_adcdev1 =
+{
+ .ad_ops = &g_adcops,
+ .ad_priv= &g_adcpriv1,
+};
+#endif
+
+/* ADC2 state */
+
+#ifdef CONFIG_STM32_ADC2
+static struct stm32_dev_s g_adcpriv2 =
+{
+#ifdef CONFIG_STM32_STM32F10XX
+ .irq = STM32_IRQ_ADC12,
+ .isr = adc12_interrupt,
+#else
+ .irq = STM32_IRQ_ADC,
+ .isr = adc123_interrupt,
+#endif
+ .intf = 2,
+ .base = STM32_ADC2_BASE,
+#ifdef ADC2_HAVE_TIMER
+ .trigger = CONFIG_STM32_ADC2_TIMTRIG,
+ .tbase = ADC2_TIMER_BASE,
+ .extsel = ADC2_EXTSEL_VALUE,
+ .pclck = ADC2_TIMER_PCLK_FREQUENCY,
+ .freq = CONFIG_STM32_ADC2_SAMPLE_FREQUENCY,
+#endif
+};
+
+static struct adc_dev_s g_adcdev2 =
+{
+ .ad_ops = &g_adcops,
+ .ad_priv= &g_adcpriv2,
+};
+#endif
+
+/* ADC3 state */
+
+#ifdef CONFIG_STM32_ADC3
+static struct stm32_dev_s g_adcpriv3 =
+{
+#ifdef CONFIG_STM32_STM32F10XX
+ .irq = STM32_IRQ_ADC3,
+ .isr = adc3_interrupt,
+#else
+ .irq = STM32_IRQ_ADC,
+ .isr = adc123_interrupt,
+#endif
+ .intf = 3,
+ .base = STM32_ADC3_BASE,
+#ifdef ADC3_HAVE_TIMER
+ .trigger = CONFIG_STM32_ADC3_TIMTRIG,
+ .tbase = ADC3_TIMER_BASE,
+ .extsel = ADC3_EXTSEL_VALUE,
+ .pclck = ADC3_TIMER_PCLK_FREQUENCY,
+ .freq = CONFIG_STM32_ADC3_SAMPLE_FREQUENCY,
+#endif
+#ifdef CONFIG_ADC_DMA
+ .rxdma_channel = DMAMAP_ADC3_2,
+ .rxfifo = g_adc3dmarxfifo,
+#endif
+};
+
+static struct adc_dev_s g_adcdev3 =
+{
+ .ad_ops = &g_adcops,
+ .ad_priv= &g_adcpriv3,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: adc_getreg
+ *
+ * Description:
+ * Read the value of an ADC register.
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static uint32_t adc_getreg(struct stm32_dev_s *priv, int offset)
+{
+ return getreg32(priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: adc_getreg
+ *
+ * Description:
+ * Read the value of an ADC register.
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void adc_putreg(struct stm32_dev_s *priv, int offset, uint32_t value)
+{
+ putreg32(value, priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: tim_getreg
+ *
+ * Description:
+ * Read the value of an ADC timer register.
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * The current contents of the specified register
+ *
+ ****************************************************************************/
+
+#ifdef ADC_HAVE_TIMER
+static uint16_t tim_getreg(struct stm32_dev_s *priv, int offset)
+{
+ return getreg16(priv->tbase + offset);
+}
+#endif
+
+/****************************************************************************
+ * Name: tim_putreg
+ *
+ * Description:
+ * Read the value of an ADC timer register.
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef ADC_HAVE_TIMER
+static void tim_putreg(struct stm32_dev_s *priv, int offset, uint16_t value)
+{
+ putreg16(value, priv->tbase + offset);
+}
+#endif
+
+/****************************************************************************
+ * Name: adc_tim_dumpregs
+ *
+ * Description:
+ * Dump all timer registers.
+ *
+ * Input parameters:
+ * priv - A reference to the ADC block status
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef ADC_HAVE_TIMER
+static void adc_tim_dumpregs(struct stm32_dev_s *priv, FAR const char *msg)
+{
+#if defined(CONFIG_DEBUG_ANALOG) && defined(CONFIG_DEBUG_VERBOSE)
+ avdbg("%s:\n", msg);
+ avdbg(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n",
+ tim_getreg(priv, STM32_GTIM_CR1_OFFSET),
+ tim_getreg(priv, STM32_GTIM_CR2_OFFSET),
+ tim_getreg(priv, STM32_GTIM_SMCR_OFFSET),
+ tim_getreg(priv, STM32_GTIM_DIER_OFFSET));
+ avdbg(" SR: %04x EGR: 0000 CCMR1: %04x CCMR2: %04x\n",
+ tim_getreg(priv, STM32_GTIM_SR_OFFSET),
+ tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET),
+ tim_getreg(priv, STM32_GTIM_CCMR2_OFFSET));
+ avdbg(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n",
+ tim_getreg(priv, STM32_GTIM_CCER_OFFSET),
+ tim_getreg(priv, STM32_GTIM_CNT_OFFSET),
+ tim_getreg(priv, STM32_GTIM_PSC_OFFSET),
+ tim_getreg(priv, STM32_GTIM_ARR_OFFSET));
+ avdbg(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n",
+ tim_getreg(priv, STM32_GTIM_CCR1_OFFSET),
+ tim_getreg(priv, STM32_GTIM_CCR2_OFFSET),
+ tim_getreg(priv, STM32_GTIM_CCR3_OFFSET),
+ tim_getreg(priv, STM32_GTIM_CCR4_OFFSET));
+
+ if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE)
+ {
+ avdbg(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n",
+ tim_getreg(priv, STM32_ATIM_RCR_OFFSET),
+ tim_getreg(priv, STM32_ATIM_BDTR_OFFSET),
+ tim_getreg(priv, STM32_ATIM_DCR_OFFSET),
+ tim_getreg(priv, STM32_ATIM_DMAR_OFFSET));
+ }
+ else
+ {
+ avdbg(" DCR: %04x DMAR: %04x\n",
+ tim_getreg(priv, STM32_GTIM_DCR_OFFSET),
+ tim_getreg(priv, STM32_GTIM_DMAR_OFFSET));
+ }
+#endif
+}
+#endif
+
+/****************************************************************************
+ * Name: adc_timstart
+ *
+ * Description:
+ * Start (or stop) the timer counter
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * enable - True: Start conversion
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+ #ifdef ADC_HAVE_TIMER
+static void adc_timstart(struct stm32_dev_s *priv, bool enable)
+{
+ uint16_t regval;
+
+ avdbg("enable: %d\n", enable);
+ regval = tim_getreg(priv, STM32_GTIM_CR1_OFFSET);
+
+ if (enable)
+ {
+ /* Start the counter */
+
+ regval |= ATIM_CR1_CEN;
+ }
+
+ else
+ {
+ /* Disable the counter */
+
+ regval &= ~ATIM_CR1_CEN;
+ }
+ tim_putreg(priv, STM32_GTIM_CR1_OFFSET, regval);
+}
+#endif
+
+/****************************************************************************
+ * Name: adc_timinit
+ *
+ * Description:
+ * Initialize the timer that drivers the ADC sampling for this channel using
+ * the pre-calculated timer divider definitions.
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef ADC_HAVE_TIMER
+static int adc_timinit(FAR struct stm32_dev_s *priv)
+{
+ uint32_t prescaler;
+ uint32_t reload;
+ uint32_t regval;
+ uint32_t timclk;
+
+ uint16_t cr1;
+ uint16_t cr2;
+ uint16_t ccmr1;
+ uint16_t ccmr2;
+ uint16_t ocmode1;
+ uint16_t ocmode2;
+ uint16_t ccenable;
+ uint16_t ccer;
+ uint16_t egr;
+
+ avdbg("Initializing timers extsel = %d\n", priv->extsel);
+
+ /* If the timer base address is zero, then this ADC was not configured to
+ * use a timer.
+ */
+
+ regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+
+#ifdef CONFIG_STM32_STM32F10XX
+ if (!priv->tbase)
+ {
+ /* Configure the ADC to use the selected timer and timer channel as the trigger
+ * EXTTRIG: External Trigger Conversion mode for regular channels DISABLE
+ */
+
+ regval &= ~ADC_CR2_EXTTRIG;
+ adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+ return OK;
+ }
+ else
+ {
+ regval |= ADC_CR2_EXTTRIG;
+ }
+#endif
+
+ /* EXTSEL selection: These bits select the external event used to trigger
+ * the start of conversion of a regular group. NOTE:
+ *
+ * - The position with with of the EXTSEL field varies from one STM32 MCU
+ * to another.
+ * - The width of the EXTSEL field varies from one STM3 MCU to another.
+ * - The value in priv->extsel is already shifted into the correct bit position.
+ */
+
+ regval &= ~ADC_CR2_EXTSEL_MASK;
+ regval |= priv->extsel;
+ adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+
+ /* Configure the timer channel to drive the ADC */
+
+ /* Caculate optimal values for the timer prescaler and for the timer reload
+ * register. If freq is the desired frequency, then
+ *
+ * reload = timclk / freq
+ * reload = (pclck / prescaler) / freq
+ *
+ * There are many solutions to do this, but the best solution will be the
+ * one that has the largest reload value and the smallest prescaler value.
+ * That is the solution that should give us the most accuracy in the timer
+ * control. Subject to:
+ *
+ * 0 <= prescaler <= 65536
+ * 1 <= reload <= 65535
+ *
+ * So ( prescaler = pclck / 65535 / freq ) would be optimal.
+ */
+
+ prescaler = 128;//(priv->pclck / priv->freq + 65534) / 65535;
+
+ /* We need to decrement the prescaler value by one, but only, the value does
+ * not underflow.
+ */
+
+ if (prescaler < 1)
+ {
+ adbg("WARNING: Prescaler underflowed.\n");
+ prescaler = 1;
+ }
+
+ /* Check for overflow */
+
+ else if (prescaler > 65536)
+ {
+ adbg("WARNING: Prescaler overflowed.\n");
+ prescaler = 65536;
+ }
+
+ timclk = priv->pclck / prescaler;
+
+ reload = priv->freq;//timclk / priv->freq;
+ if (reload < 1)
+ {
+ adbg("WARNING: Reload value underflowed.\n");
+ reload = 1;
+ }
+ else if (reload > 65535)
+ {
+ adbg("WARNING: Reload value overflowed.\n");
+ reload = 65535;
+ }
+
+ /* Set up the timer CR1 register */
+
+ cr1 = tim_getreg(priv, STM32_GTIM_CR1_OFFSET);
+
+ /* Disable the timer until we get it configured */
+
+ adc_timstart(priv, false);
+
+ /* Select the Counter Mode == count up:
+ *
+ * ATIM_CR1_EDGE: The counter counts up or down depending on the
+ * direction bit(DIR).
+ * ATIM_CR1_DIR: 0: count up, 1: count down
+ */
+
+ cr1 &= ~(ATIM_CR1_DIR | ATIM_CR1_CMS_MASK);
+ cr1 |= ATIM_CR1_EDGE;
+
+ /* Set the clock division to zero for all */
+
+ cr1 &= ~GTIM_CR1_CKD_MASK;
+ tim_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+ /* Set the reload and prescaler values */
+
+ tim_putreg(priv, STM32_GTIM_PSC_OFFSET, prescaler-1);
+ tim_putreg(priv, STM32_GTIM_ARR_OFFSET, reload);
+
+ /* Clear the advanced timers repitition counter in TIM1 */
+
+ if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE)
+ {
+ tim_putreg(priv, STM32_ATIM_RCR_OFFSET, 0);
+ tim_putreg(priv, STM32_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE); /* Check me */
+ }
+
+ /* TIMx event generation: Bit 0 UG: Update generation */
+
+ tim_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+
+ /* Handle channel specific setup */
+
+ ocmode1 = 0;
+ ocmode2 = 0;
+
+ switch (priv->trigger)
+ {
+ case 0: /* TimerX CC1 event */
+ {
+ ccenable = ATIM_CCER_CC1E;
+ ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) |
+ (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) |
+ ATIM_CCMR1_OC1PE;
+
+ /* Set the event CC1 */
+
+ egr = ATIM_EGR_CC1G;
+
+ /* Set the duty cycle by writing to the CCR register for this channel */
+
+ tim_putreg(priv, STM32_GTIM_CCR1_OFFSET, (uint16_t)(reload >> 1));
+ }
+ break;
+
+ case 1: /* TimerX CC2 event */
+ {
+ ccenable = ATIM_CCER_CC2E;
+ ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) |
+ (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) |
+ ATIM_CCMR1_OC2PE;
+
+ /* Set the event CC2 */
+
+ egr = ATIM_EGR_CC2G;
+
+ /* Set the duty cycle by writing to the CCR register for this channel */
+
+ tim_putreg(priv, STM32_GTIM_CCR2_OFFSET, (uint16_t)(reload >> 1));
+ }
+ break;
+
+ case 2: /* TimerX CC3 event */
+ {
+ ccenable = ATIM_CCER_CC3E;
+ ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) |
+ (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) |
+ ATIM_CCMR2_OC3PE;
+
+ /* Set the event CC3 */
+
+ egr = ATIM_EGR_CC3G;
+
+ /* Set the duty cycle by writing to the CCR register for this channel */
+
+ tim_putreg(priv, STM32_GTIM_CCR3_OFFSET, (uint16_t)(reload >> 1));
+ }
+ break;
+
+ case 3: /* TimerX CC4 event */
+ {
+ ccenable = ATIM_CCER_CC4E;
+ ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) |
+ (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) |
+ ATIM_CCMR2_OC4PE;
+
+ /* Set the event CC4 */
+
+ egr = ATIM_EGR_CC4G;
+
+ /* Set the duty cycle by writing to the CCR register for this channel */
+
+ tim_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1));
+ }
+ break;
+
+ case 4: /* TimerX TRGO event */
+ {
+#warning "TRGO support not yet implemented"
+
+ /* Set the event TRGO */
+
+ egr = GTIM_EGR_TG;
+
+ /* Set the duty cycle by writing to the CCR register for this channel */
+
+ tim_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1));
+ }
+ break;
+
+ default:
+ adbg("No such trigger: %d\n", priv->trigger);
+ return -EINVAL;
+ }
+
+ /* Disable the Channel by resetting the CCxE Bit in the CCER register */
+
+ ccer = tim_getreg(priv, STM32_GTIM_CCER_OFFSET);
+ ccer &= ~ccenable;
+ tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
+
+ /* Fetch the CR2, CCMR1, and CCMR2 register (already have cr1 and ccer) */
+
+ cr2 = tim_getreg(priv, STM32_GTIM_CR2_OFFSET);
+ ccmr1 = tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET);
+ ccmr2 = tim_getreg(priv, STM32_GTIM_CCMR2_OFFSET);
+
+ /* Reset the Output Compare Mode Bits and set the select output compare mode */
+
+ ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE |
+ ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE);
+ ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE |
+ ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE);
+ ccmr1 |= ocmode1;
+ ccmr2 |= ocmode2;
+
+ /* Reset the output polarity level of all channels (selects high polarity)*/
+
+ ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P | ATIM_CCER_CC3P | ATIM_CCER_CC4P);
+
+ /* Enable the output state of the selected channel (only) */
+
+ ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E | ATIM_CCER_CC3E | ATIM_CCER_CC4E);
+ ccer |= ccenable;
+
+ if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE)
+ {
+ /* Reset output N polarity level, output N state, output compre state,
+ * output compare N idle state.
+ */
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP |
+ ATIM_CCER_CC3NE | ATIM_CCER_CC3NP | ATIM_CCER_CC4NP);
+#else
+ ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP |
+ ATIM_CCER_CC3NE | ATIM_CCER_CC3NP);
+#endif
+
+ /* Reset the output compare and output compare N IDLE State */
+
+ cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | ATIM_CR2_OIS2 | ATIM_CR2_OIS2N |
+ ATIM_CR2_OIS3 | ATIM_CR2_OIS3N | ATIM_CR2_OIS4);
+ }
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ else
+ {
+ ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP | GTIM_CCER_CC4NP);
+ }
+#endif
+
+ /* Save the modified register values */
+
+ tim_putreg(priv, STM32_GTIM_CR2_OFFSET, cr2);
+ tim_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
+ tim_putreg(priv, STM32_GTIM_CCMR2_OFFSET, ccmr2);
+ tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
+ tim_putreg(priv, STM32_GTIM_EGR_OFFSET, egr);
+
+ /* Set the ARR Preload Bit */
+
+ cr1 = tim_getreg(priv, STM32_GTIM_CR1_OFFSET);
+ cr1 |= GTIM_CR1_ARPE;
+ tim_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+ /* Enable the timer counter
+ * All but the CEN bit with the default config in CR1
+ */
+
+ adc_timstart(priv, true);
+
+ adc_tim_dumpregs(priv, "After starting Timers");
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: adc_startconv
+ *
+ * Description:
+ * Start (or stop) the ADC conversion process in DMA mode
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * enable - True: Start conversion
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+static void adc_startconv(struct stm32_dev_s *priv, bool enable)
+{
+ uint32_t regval;
+
+ avdbg("enable: %d\n", enable);
+
+ regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+ if (enable)
+ {
+ /* Start conversion of regular channles */
+
+ regval |= ADC_CR2_SWSTART;
+ }
+ else
+ {
+ /* Disable the conversion of regular channels */
+
+ regval &= ~ADC_CR2_SWSTART;
+ }
+ adc_putreg(priv, STM32_ADC_CR2_OFFSET,regval);
+}
+#endif
+
+/****************************************************************************
+ * Name: adc_rccreset
+ *
+ * Description:
+ * Deinitializes the ADCx peripheral registers to their default
+ * reset values. It could set all the ADCs configured.
+ *
+ * Input Parameters:
+ * regaddr - The register to read
+ * reset - Condition, set or reset
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void adc_rccreset(struct stm32_dev_s *priv, bool reset)
+{
+ irqstate_t flags;
+ uint32_t regval;
+ uint32_t adcbit;
+
+ /* Pick the appropriate bit in the APB2 reset register */
+
+#ifdef CONFIG_STM32_STM32F10XX
+ /* For the STM32 F1, there is an individual bit to reset each ADC. */
+
+ switch (priv->intf)
+ {
+#ifdef CONFIG_STM32_ADC1
+ case 1:
+ adcbit = RCC_APB2RSTR_ADC1RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_ADC2
+ case 2:
+ adcbit = RCC_APB2RSTR_ADC2RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_ADC3
+ case 3:
+ adcbit = RCC_APB2RSTR_ADC3RST;
+ break;
+#endif
+ default:
+ return;
+ }
+
+#else
+ /* For the STM32 F4, there is one common reset for all ADC block.
+ * THIS will probably cause some problems!
+ */
+
+ adcbit = RCC_APB2RSTR_ADCRST;
+#endif
+
+ /* Disable interrupts. This is necessary because the APB2RTSR register
+ * is used by several different drivers.
+ */
+
+ flags = irqsave();
+
+ /* Set or clear the selected bit in the APB2 reset register */
+
+ regval = getreg32(STM32_RCC_APB2RSTR);
+ if (reset)
+ {
+ /* Enable ADC reset state */
+
+ regval |= adcbit;
+ }
+ else
+ {
+ /* Release ADC from reset state */
+
+ regval &= ~adcbit;
+ }
+ putreg32(regval, STM32_RCC_APB2RSTR);
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: up_dma_setup
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ADC_DMA
+static int up_dma_setup(FAR struct adc_dev_s *dev)
+{
+
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
+ int result;
+ uint32_t regval;
+
+//
+// result = up_setup(dev);
+// if (result != OK)
+// {
+// return result;
+// }
+
+ /* Acquire the DMA channel. This should always succeed. */
+
+ priv->rxdma = stm32_dmachannel(priv->rxdma_channel);
+
+ /* Configure for circular DMA reception into the RX fifo */
+
+ stm32_dmasetup(priv->rxdma,
+ priv->base + STM32_ADC_DR_OFFSET,
+ (uint32_t)priv->rxfifo,
+ 4,//buffersize
+ DMA_SCR_DIR_P2M |
+ DMA_SCR_CIRC |
+ DMA_SCR_MINC |
+ DMA_SCR_PSIZE_16BITS |
+ DMA_SCR_MSIZE_16BITS |
+ DMA_SCR_PBURST_SINGLE |
+ DMA_SCR_MBURST_SINGLE);
+
+ /* Reset our DMA shadow pointer to match the address just
+ * programmed above.
+ */
+
+ //priv->rxdmanext = 0;
+
+ /* Enable DMA for the ADC */
+
+ /* Start the DMA channel, and arrange for callbacks at the half and
+ * full points in the FIFO. This ensures that we have half a FIFO
+ * worth of time to claim bytes before they are overwritten.
+ */
+
+ stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)dev, false);
+
+ return OK;
+}
+#endif
+/****************************************************************************
+ * Name: up_dma_rxcallback
+ *
+ * Description:
+
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ADC_DMA
+static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, FAR struct adc_dev_s *dev)
+{
+ //struct up_dev_s *priv = (struct up_dev_s*)arg;
+ //uint32_t regval;
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
+ //struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+
+ //if (priv->rxenable && up_dma_rxavailable(&priv->dev))
+ {
+ /* Give the ADC data to the ADC driver. adc_receive accepts 3 parameters:
+ *
+ * 1) The first is the ADC device instance for this ADC block.
+ * 2) The second is the channel number for the data, and
+ * 3) The third is the converted data for the channel.
+ */
+
+
+ adc_receive(dev, 10, (int32_t)g_adc3dmarxfifo[1]);
+ adc_receive(dev, 11, (int32_t)g_adc3dmarxfifo[2]);
+ adc_receive(dev, 12, (int32_t)g_adc3dmarxfifo[3]);
+ adc_receive(dev, 13, (int32_t)g_adc3dmarxfifo[0]);
+
+
+ /* Set the channel number of the next channel that will complete conversion */
+
+ priv->current++;
+
+ if (priv->current >= priv->nchannels)
+ {
+ /* Restart the conversion sequence from the beginning */
+
+ priv->current = 0;
+ }
+
+
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_shutdown
+ *
+ * Description:
+ * Disable the DMA
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ADC_DMA
+static void up_dma_shutdown(struct adc_dev_s *dev)
+{
+
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
+
+
+ /* Stop the DMA channel */
+
+ stm32_dmastop(priv->rxdma);
+
+ /* Release the DMA channel */
+
+ stm32_dmafree(priv->rxdma);
+ priv->rxdma = NULL;
+}
+#endif
+
+
+/*******************************************************************************
+ * Name: adc_enable
+ *
+ * Description : Enables or disables the specified ADC peripheral.
+ * Also, starts a conversion when the ADC is not
+ * triggered by timers
+ *
+ * Input Parameters:
+ *
+ * enable - true: enable ADC conversion
+ * false: disable ADC conversion
+ *
+ * Returned Value:
+ *
+ *******************************************************************************/
+
+static void adc_enable(FAR struct stm32_dev_s *priv, bool enable)
+{
+ uint32_t regval;
+
+ // avdbg("enable: %d\n", enable);
+
+ regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+ if (enable)
+ {
+ regval |= ADC_CR2_ADON;
+ }
+ else
+ {
+ regval &= ~ADC_CR2_ADON;
+ }
+ adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: adc_reset
+ *
+ * Description:
+ * Reset the ADC device. Called early to initialize the hardware. This
+ * is called, before adc_setup() and on error conditions.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void adc_reset(FAR struct adc_dev_s *dev)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
+ irqstate_t flags;
+ uint32_t regval;
+ int offset;
+ int i;
+ int ret;
+
+ avdbg("intf: ADC%d\n", priv->intf);
+ flags = irqsave();
+
+ /* Enable ADC reset state */
+
+ adc_rccreset(priv, true);
+
+ /* Release ADC from reset state */
+
+ adc_rccreset(priv, false);
+
+ /* Initialize the ADC data structures */
+
+ /* Initialize the watchdog high threshold register */
+
+ adc_putreg(priv, STM32_ADC_HTR_OFFSET, 0x00000fff);
+
+ /* Initialize the watchdog low threshold register */
+
+ adc_putreg(priv, STM32_ADC_LTR_OFFSET, 0x00000000);
+
+
+ /* Initialize the same sample time for each ADC 55.5 cycles
+ *
+ * During sample cycles channel selection bits must remain unchanged.
+ *
+ * 000: 1.5 cycles
+ * 001: 7.5 cycles
+ * 010: 13.5 cycles
+ * 011: 28.5 cycles
+ * 100: 41.5 cycles
+ * 101: 55.5 cycles
+ * 110: 71.5 cycles
+ * 111: 239.5 cycles
+ */
+
+ adc_putreg(priv, STM32_ADC_SMPR1_OFFSET, 0x00b6db6d);
+ adc_putreg(priv, STM32_ADC_SMPR2_OFFSET, 0x00b6db6d);
+
+ /* ADC CR1 Configuration */
+
+ regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET);
+
+ /* Set mode configuration (Independent mode) */
+
+#ifdef CONFIG_STM32_STM32F10XX
+ regval |= ADC_CR1_IND;
+#endif
+
+ /* Initialize the Analog watchdog enable */
+
+ regval |= ADC_CR1_AWDEN;
+ regval |= (priv->chanlist[0] << ADC_CR1_AWDCH_SHIFT);
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+
+ /* Set the resolution of the conversion */
+
+ regval |= ACD_CR1_RES_12BIT;
+#endif
+
+ adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
+
+ /* ADC CR2 Configuration */
+
+ regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+
+ /* Clear CONT, continuous mode disable */
+
+ regval &= ~ADC_CR2_CONT;
+
+ /* Set ALIGN (Right = 0) */
+
+ regval &= ~ADC_CR2_ALIGN;
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ /* External trigger enable for regular channels */
+
+ regval |= ACD_CR2_EXTEN_RISING;
+#endif
+
+ adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+
+ /* Configuration of the channel conversions */
+
+ regval = adc_getreg(priv, STM32_ADC_SQR3_OFFSET) & ADC_SQR3_RESERVED;
+ for (i = 0, offset = 0; i < priv->nchannels && i < 6; i++, offset += 5)
+ {
+ regval |= (uint32_t)priv->chanlist[i] << offset;
+ }
+ adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval);
+
+ regval = adc_getreg(priv, STM32_ADC_SQR2_OFFSET) & ADC_SQR2_RESERVED;
+ for (i = 6, offset = 0; i < priv->nchannels && i < 12; i++, offset += 5)
+ {
+ regval |= (uint32_t)priv->chanlist[i] << offset;
+ }
+ adc_putreg(priv, STM32_ADC_SQR2_OFFSET, regval);
+
+ regval = adc_getreg(priv, STM32_ADC_SQR1_OFFSET) & ADC_SQR1_RESERVED;
+ for (i = 12, offset = 0; i < priv->nchannels && i < 16; i++, offset += 5)
+ {
+ regval |= (uint32_t)priv->chanlist[i] << offset;
+ }
+ /* Set the number of conversions */
+
+ DEBUGASSERT(priv->nchannels <= ADC_MAX_SAMPLES);
+
+ regval |= (((uint32_t)priv->nchannels-1) << ADC_SQR1_L_SHIFT);
+ adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
+
+ /* ADC CCR configuration */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ regval = getreg32(STM32_ADC_CCR);
+ regval &= ~(ADC_CCR_MULTI_MASK | ADC_CCR_DELAY_MASK | ADC_CCR_DDS | ADC_CCR_DMA_MASK |
+ ADC_CCR_ADCPRE_MASK | ADC_CCR_VBATE | ADC_CCR_TSVREFE);
+ regval |= (ADC_CCR_MULTI_NONE | ADC_CCR_DMA_DISABLED | ADC_CCR_ADCPRE_DIV2);
+ putreg32(regval, STM32_ADC_CCR);
+#endif
+
+
+
+ /* Set the channel index of the first conversion */
+
+ priv->current = 0;
+
+ /* Set ADON to wake up the ADC from Power Down state. */
+
+ adc_enable(priv, true);
+
+#ifdef ADC_HAVE_TIMER
+ ret = adc_timinit(priv);
+ if (ret!=OK)
+ {
+ adbg("Error initializing the timers\n");
+ }
+#else
+#ifdef CONFIG_STM32_STM32F10XX
+ /* Set ADON (Again) to start the conversion. Only if Timers are not
+ * configured as triggers
+ */
+
+ adc_enable(priv, true);
+#else
+#ifdef CONFIG_ADC_DMA
+ //nothing
+#else
+ adc_startconv(priv, true);
+#endif
+#endif /* CONFIG_STM32_STM32F10XX */
+#endif /* ADC_HAVE_TIMER */
+
+
+ irqrestore(flags);
+
+// avdbg("SR: 0x%08x CR1: 0x%08x CR2: 0x%08x\n",
+// adc_getreg(priv, STM32_ADC_SR_OFFSET),
+// adc_getreg(priv, STM32_ADC_CR1_OFFSET),
+// adc_getreg(priv, STM32_ADC_CR2_OFFSET));
+// avdbg("SQR1: 0x%08x SQR2: 0x%08x SQR3: 0x%08x\n",
+// adc_getreg(priv, STM32_ADC_SQR1_OFFSET),
+// adc_getreg(priv, STM32_ADC_SQR2_OFFSET),
+// adc_getreg(priv, STM32_ADC_SQR3_OFFSET));
+//#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+// avdbg("CCR: 0x%08x\n",
+// getreg32(STM32_ADC_CCR));
+//#endif
+}
+
+/****************************************************************************
+ * Name: adc_setup
+ *
+ * Description:
+ * Configure the ADC. This method is called the first time that the ADC
+ * device is opened. This will occur when the port is first opened.
+ * This setup includes configuring and attaching ADC interrupts. Interrupts
+ * are all disabled upon return.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static int adc_setup(FAR struct adc_dev_s *dev)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
+ int ret;
+ uint32_t regval;
+
+
+ /* the adc seems to need a full reset to be enabled correctly */
+ adc_reset(dev);
+
+#ifndef CONFIG_ADC_DMA
+ /* Attach the ADC interrupt */
+
+ ret = irq_attach(priv->irq, priv->isr);
+ if (ret == OK)
+ {
+ /* Enable the ADC interrupt */
+
+ avdbg("Enable the ADC interrupt: irq=%d\n", priv->irq);
+ up_enable_irq(priv->irq);
+ }
+#endif
+
+#ifdef CONFIG_ADC_DMA
+ up_dma_setup(dev);
+
+
+//#ifndef ADC_HAVE_TIMER
+// /*disable external trigger*/
+// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+// regval |= ACD_CR2_EXTEN_NONE;
+// //regval |= ADC_CR1_DISCEN;
+// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+//#else
+// /*enable external trigger*/
+// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+// regval |=ADC_CR2_EXTSEL_T4CC4;
+// regval |=ACD_CR2_EXTEN_BOTH;
+// //regval |= ADC_CR2_CONT;
+// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+//#endif
+
+
+ /*enable scan mode*/
+ regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET);
+ regval |= ADC_CR1_SCAN;
+ //regval |= ADC_CR1_DISCEN;
+ adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
+
+ /* Enable DMA request after last transfer (Single-ADC mode) */
+ //ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
+ regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+ regval |= ADC_CR2_DDS;
+ adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+
+ /* Enable ADC3 DMA */
+ // ADC_DMACmd(ADC3, ENABLE);
+ regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+ regval |= ADC_CR2_DMA;
+ adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+#endif
+
+
+#ifndef ADC_HAVE_TIMER
+ /*set continuous conversion */
+ regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+ regval |= ADC_CR2_CONT;
+ adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+#endif
+
+ /* Enable ADC3 */
+ //ADC_Cmd(ADC3, ENABLE);
+ regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+ regval |= ADC_CR2_ADON;
+ adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+
+//// /*start conversion*/
+// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
+// regval |= ADC_CR2_SWSTART;
+// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
+
+
+
+
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: adc_shutdown
+ *
+ * Description:
+ * Disable the ADC. This method is called when the ADC device is closed.
+ * This method reverses the operation the setup method.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void adc_shutdown(FAR struct adc_dev_s *dev)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
+
+#ifdef CONFIG_ADC_DMA
+ up_dma_shutdown(dev);
+#endif
+
+#ifdef ADC_HAVE_TIMER
+ /* stop adc timer */
+ adc_timstart(priv, false);
+#endif
+
+ /* power down ADC */
+ adc_enable(priv, false);
+
+ adc_rxint(priv, false);
+
+ /* Disable ADC interrupts and detach the ADC interrupt handler */
+ up_disable_irq(priv->irq);
+// irq_detach(priv->irq);
+
+
+
+
+}
+
+/****************************************************************************
+ * Name: adc_rxint
+ *
+ * Description:
+ * Call to enable or disable RX interrupts.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
+ uint32_t regval;
+
+ avdbg("intf: %d enable: %d\n", priv->intf, enable);
+
+ regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET);
+ if (enable)
+ {
+ /* Enable the end-of-conversion ADC and analog watchdog interrupts */
+
+ regval |= ADC_CR1_ALLINTS;
+ }
+ else
+ {
+ /* Disable all ADC interrupts */
+
+ regval &= ~ADC_CR1_ALLINTS;
+ }
+ adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: adc_ioctl
+ *
+ * Description:
+ * All ioctl calls will be routed through this method.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
+{
+ return -ENOTTY;
+}
+
+/****************************************************************************
+ * Name: adc_interrupt
+ *
+ * Description:
+ * Common ADC interrupt handler.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static int adc_interrupt(FAR struct adc_dev_s *dev)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
+ uint32_t adcsr;
+ int32_t value;
+
+ /* Identifies the interruption AWD, OVR or EOC */
+
+ adcsr = adc_getreg(priv, STM32_ADC_SR_OFFSET);
+ if ((adcsr & ADC_SR_AWD) != 0)
+ {
+ alldbg("WARNING: Analog Watchdog, Value converted out of range!\n");
+ }
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ if ((adcsr & ADC_SR_OVR) != 0)
+ {
+ alldbg("WARNING: Overrun has ocurred!\n");
+ }
+#endif
+
+ /* EOC: End of conversion */
+
+ if ((adcsr & ADC_SR_EOC) != 0)
+ {
+ /* Read the converted value and clear EOC bit
+ * (It is cleared by reading the ADC_DR)
+ */
+
+ value = adc_getreg(priv, STM32_ADC_DR_OFFSET);
+ value &= ADC_DR_DATA_MASK;
+
+ /* Give the ADC data to the ADC driver. adc_receive accepts 3 parameters:
+ *
+ * 1) The first is the ADC device instance for this ADC block.
+ * 2) The second is the channel number for the data, and
+ * 3) The third is the converted data for the channel.
+ */
+
+ adc_receive(dev, priv->chanlist[priv->current], value);
+
+ /* Set the channel number of the next channel that will complete conversion */
+
+ priv->current++;
+
+ if (priv->current >= priv->nchannels)
+ {
+ /* Restart the conversion sequence from the beginning */
+
+ priv->current = 0;
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: adc12_interrupt
+ *
+ * Description:
+ * ADC12 interrupt handler for the STM32 F1 family.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F10XX) && (defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2))
+static int adc12_interrupt(int irq, void *context)
+{
+ uint32_t regval;
+ uint32_t pending;
+
+ /* Check for pending ADC1 interrupts */
+
+#ifdef CONFIG_STM32_ADC1
+ regval = getreg32(STM32_ADC1_SR);
+ pending = regval & ADC_SR_ALLINTS;
+ if (pending != 0)
+ {
+ adc_interrupt(&g_adcdev1);
+ regval &= ~pending;
+ putreg32(regval, STM32_ADC1_SR);
+ }
+#endif
+
+ /* Check for pending ADC2 interrupts */
+
+#ifdef CONFIG_STM32_ADC2
+ regval = getreg32(STM32_ADC2_SR);
+ pending = regval & ADC_SR_ALLINTS;
+ if (pending != 0)
+ {
+ adc_interrupt(&g_adcdev2);
+ regval &= ~pending;
+ putreg32(regval, STM32_ADC2_SR);
+ }
+#endif
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: adc3_interrupt
+ *
+ * Description:
+ * ADC1/2 interrupt handler for the STM32 F1 family.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+#if defined (CONFIG_STM32_STM32F10XX) && defined (CONFIG_STM32_ADC3)
+static int adc3_interrupt(int irq, void *context)
+{
+ uint32_t regval;
+ uint32_t pending;
+
+ /* Check for pending ADC3 interrupts */
+
+ regval = getreg32(STM32_ADC3_SR);
+ pending = regval & ADC_SR_ALLINTS;
+ if (pending != 0)
+ {
+ adc_interrupt(&g_adcdev3);
+ regval &= ~pending;
+ putreg32(regval, STM32_ADC3_SR);
+ }
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: adc123_interrupt
+ *
+ * Description:
+ * ADC1/2/3 interrupt handler for the STM32 F4 family.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+static int adc123_interrupt(int irq, void *context)
+{
+ uint32_t regval;
+ uint32_t pending;
+
+ /* Check for pending ADC1 interrupts */
+
+#ifdef CONFIG_STM32_ADC1
+ regval = getreg32(STM32_ADC1_SR);
+ pending = regval & ADC_SR_ALLINTS;
+ if (pending != 0)
+ {
+ adc_interrupt(&g_adcdev1);
+ regval &= ~pending;
+ putreg32(regval, STM32_ADC1_SR);
+ }
+#endif
+
+ /* Check for pending ADC2 interrupts */
+
+#ifdef CONFIG_STM32_ADC2
+ regval = getreg32(STM32_ADC2_SR);
+ pending = regval & ADC_SR_ALLINTS;
+ if (pending != 0)
+ {
+ adc_interrupt(&g_adcdev2);
+ regval &= ~pending;
+ putreg32(regval, STM32_ADC2_SR);
+ }
+#endif
+
+ /* Check for pending ADC3 interrupts */
+
+#ifdef CONFIG_STM32_ADC3
+ regval = getreg32(STM32_ADC3_SR);
+ pending = regval & ADC_SR_ALLINTS;
+ if (pending != 0)
+ {
+ adc_interrupt(&g_adcdev3);
+ regval &= ~pending;
+ putreg32(regval, STM32_ADC3_SR);
+ }
+#endif
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_adcinitialize
+ *
+ * Description:
+ * Initialize the ADC.
+ *
+ * The logic is, save nchannels : # of channels (conversions) in ADC_SQR1_L
+ * Then, take the chanlist array and store it in the SQR Regs,
+ * chanlist[0] -> ADC_SQR3_SQ1
+ * chanlist[1] -> ADC_SQR3_SQ2
+ * ...
+ * chanlist[15]-> ADC_SQR1_SQ16
+ *
+ * up to
+ * chanlist[nchannels]
+ *
+ * Input Parameters:
+ * intf - Could be {1,2,3} for ADC1, ADC2, or ADC3
+ * chanlist - The list of channels
+ * nchannels - Number of channels
+ *
+ * Returned Value:
+ * Valid ADC device structure reference on succcess; a NULL on failure
+ *
+ ****************************************************************************/
+
+struct adc_dev_s *stm32_adcinitialize(int intf, const uint8_t *chanlist, int nchannels)
+{
+ FAR struct adc_dev_s *dev;
+ FAR struct stm32_dev_s *priv;
+
+ avdbg("intf: %d nchannels: %d\n", intf, nchannels);
+
+#ifdef CONFIG_STM32_ADC1
+ if (intf == 1)
+ {
+ avdbg("ADC1 Selected\n");
+ dev = &g_adcdev1;
+ }
+ else
+#endif
+#ifdef CONFIG_STM32_ADC2
+ if (intf == 2)
+ {
+ avdbg("ADC2 Selected\n");
+ dev = &g_adcdev2;
+ }
+ else
+#endif
+#ifdef CONFIG_STM32_ADC3
+ if (intf == 3)
+ {
+ avdbg("ADC3 Selected\n");
+ dev = &g_adcdev3;
+ }
+ else
+#endif
+ {
+ adbg("No ADC interface defined\n");
+ return NULL;
+ }
+
+ /* Configure the selected ADC */
+
+ priv = dev->ad_priv;
+
+ DEBUGASSERT(nchannels <= ADC_MAX_SAMPLES);
+ priv->nchannels = nchannels;
+
+ memcpy(priv->chanlist, chanlist, nchannels);
+ return dev;
+}
+
+#endif /* CONFIG_STM32_ADC || CONFIG_STM32_ADC2 || CONFIG_STM32_ADC3 */
+#endif /* CONFIG_ADC */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_adc.h b/nuttx/arch/arm/src/stm32/stm32_adc.h
new file mode 100644
index 000000000..c25da3830
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_adc.h
@@ -0,0 +1,596 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_adc.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_STM32_ADC_H
+#define __ARCH_ARM_SRC_STM32_STM32_ADC_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_adc.h"
+
+#include <nuttx/analog/adc.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* Timer devices may be used for different purposes. One special purpose is to
+ * control periodic ADC sampling. If CONFIG_STM32_TIMn is defined then
+ * CONFIG_STM32_TIMn_ADC must also be defined to indicate that timer "n" is intended
+ * to be used for that purpose.
+ */
+
+/* For the STM32 F1 line, timers 1-4 may be used. For STM32 F4 line, timers 1-5 and
+ * 8 may be used.
+ */
+
+#ifndef CONFIG_STM32_TIM1
+# undef CONFIG_STM32_TIM1_ADC
+# undef CONFIG_STM32_TIM1_ADC1
+# undef CONFIG_STM32_TIM1_ADC2
+# undef CONFIG_STM32_TIM1_ADC3
+#endif
+#ifndef CONFIG_STM32_TIM2
+# undef CONFIG_STM32_TIM2_ADC
+# undef CONFIG_STM32_TIM2_ADC1
+# undef CONFIG_STM32_TIM2_ADC2
+# undef CONFIG_STM32_TIM2_ADC3
+#endif
+#ifndef CONFIG_STM32_TIM3
+# undef CONFIG_STM32_TIM3_ADC
+# undef CONFIG_STM32_TIM3_ADC1
+# undef CONFIG_STM32_TIM3_ADC2
+# undef CONFIG_STM32_TIM3_ADC3
+#endif
+#ifndef CONFIG_STM32_TIM4
+# undef CONFIG_STM32_TIM4_ADC
+# undef CONFIG_STM32_TIM4_ADC1
+# undef CONFIG_STM32_TIM4_ADC2
+# undef CONFIG_STM32_TIM4_ADC3
+#endif
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# ifndef CONFIG_STM32_TIM5
+# undef CONFIG_STM32_TIM5_ADC
+# undef CONFIG_STM32_TIM5_ADC1
+# undef CONFIG_STM32_TIM5_ADC2
+# undef CONFIG_STM32_TIM5_ADC3
+# endif
+# ifndef CONFIG_STM32_TIM8
+# undef CONFIG_STM32_TIM8_ADC
+# undef CONFIG_STM32_TIM8_ADC1
+# undef CONFIG_STM32_TIM8_ADC2
+# undef CONFIG_STM32_TIM8_ADC3
+# endif
+#else
+# undef CONFIG_STM32_TIM5_ADC
+# undef CONFIG_STM32_TIM5_ADC1
+# undef CONFIG_STM32_TIM5_ADC2
+# undef CONFIG_STM32_TIM5_ADC3
+# undef CONFIG_STM32_TIM8_ADC
+# undef CONFIG_STM32_TIM8_ADC1
+# undef CONFIG_STM32_TIM8_ADC2
+# undef CONFIG_STM32_TIM8_ADC3
+#endif
+
+/* Timers 6, 7, and 10-14 are not used with the ADC by any supported family */
+
+#undef CONFIG_STM32_TIM6_ADC
+#undef CONFIG_STM32_TIM6_ADC1
+#undef CONFIG_STM32_TIM6_ADC2
+#undef CONFIG_STM32_TIM6_ADC3
+#undef CONFIG_STM32_TIM7_ADC
+#undef CONFIG_STM32_TIM7_ADC1
+#undef CONFIG_STM32_TIM7_ADC2
+#undef CONFIG_STM32_TIM7_ADC3
+#undef CONFIG_STM32_TIM9_ADC
+#undef CONFIG_STM32_TIM9_ADC1
+#undef CONFIG_STM32_TIM9_ADC2
+#undef CONFIG_STM32_TIM9_ADC3
+#undef CONFIG_STM32_TIM10_ADC
+#undef CONFIG_STM32_TIM10_ADC1
+#undef CONFIG_STM32_TIM10_ADC2
+#undef CONFIG_STM32_TIM10_ADC3
+#undef CONFIG_STM32_TIM11_ADC
+#undef CONFIG_STM32_TIM11_ADC1
+#undef CONFIG_STM32_TIM11_ADC2
+#undef CONFIG_STM32_TIM11_ADC3
+#undef CONFIG_STM32_TIM12_ADC
+#undef CONFIG_STM32_TIM12_ADC1
+#undef CONFIG_STM32_TIM12_ADC2
+#undef CONFIG_STM32_TIM12_ADC3
+#undef CONFIG_STM32_TIM13_ADC
+#undef CONFIG_STM32_TIM13_ADC1
+#undef CONFIG_STM32_TIM13_ADC2
+#undef CONFIG_STM32_TIM13_ADC3
+#undef CONFIG_STM32_TIM14_ADC
+#undef CONFIG_STM32_TIM14_ADC1
+#undef CONFIG_STM32_TIM14_ADC2
+#undef CONFIG_STM32_TIM14_ADC3
+
+/* Up to 3 ADC interfaces are supported */
+
+#if STM32_NADC < 3
+# undef CONFIG_STM32_ADC3
+#endif
+
+#if STM32_NADC < 2
+# undef CONFIG_STM32_ADC2
+#endif
+
+#if STM32_NADC < 1
+# undef CONFIG_STM32_ADC1
+#endif
+
+#if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3)
+
+/* Timer configuration: If a timer trigger is specified, then get information
+ * about the timer.
+ */
+
+#if defined(CONFIG_STM32_TIM1_ADC1)
+# define ADC1_HAVE_TIMER 1
+# define ADC1_TIMER_BASE STM32_TIM1_BASE
+# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN
+#elif defined(CONFIG_STM32_TIM2_ADC1)
+# define ADC1_HAVE_TIMER 1
+# define ADC1_TIMER_BASE STM32_TIM2_BASE
+# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN
+#elif defined(CONFIG_STM32_TIM3_ADC1)
+# define ADC1_HAVE_TIMER 1
+# define ADC1_TIMER_BASE STM32_TIM3_BASE
+# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN
+#elif defined(CONFIG_STM32_TIM4_ADC1)
+# define ADC1_HAVE_TIMER 1
+# define ADC1_TIMER_BASE STM32_TIM4_BASE
+# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN
+#elif defined(CONFIG_STM32_TIM5_ADC1)
+# define ADC1_HAVE_TIMER 1
+# define ADC1_TIMER_BASE STM32_TIM5_BASE
+# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM5_CLKIN
+#elif defined(CONFIG_STM32_TIM8_ADC1)
+# define ADC1_HAVE_TIMER 1
+# define ADC1_TIMER_BASE STM32_TIM8_BASE
+# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN
+#else
+# undef ADC1_HAVE_TIMER
+#endif
+
+#ifdef ADC1_HAVE_TIMER
+# ifndef CONFIG_STM32_ADC1_SAMPLE_FREQUENCY
+# error "CONFIG_STM32_ADC1_SAMPLE_FREQUENCY not defined"
+# endif
+# ifndef CONFIG_STM32_ADC1_TIMTRIG
+# error "CONFIG_STM32_ADC1_TIMTRIG not defined"
+# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO"
+# endif
+#endif
+
+#if defined(CONFIG_STM32_TIM1_ADC2)
+# define ADC2_HAVE_TIMER 1
+# define ADC2_TIMER_BASE STM32_TIM1_BASE
+# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN
+#elif defined(CONFIG_STM32_TIM2_ADC2)
+# define ADC2_HAVE_TIMER 1
+# define ADC2_TIMER_BASE STM32_TIM2_BASE
+# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN
+#elif defined(CONFIG_STM32_TIM3_ADC2)
+# define ADC2_HAVE_TIMER 1
+# define ADC2_TIMER_BASE STM32_TIM3_BASE
+# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN
+#elif defined(CONFIG_STM32_TIM4_ADC2)
+# define ADC2_HAVE_TIMER 1
+# define ADC2_TIMER_BASE STM32_TIM4_BASE
+# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN
+#elif defined(CONFIG_STM32_TIM5_ADC2)
+# define ADC2_HAVE_TIMER 1
+# define ADC2_TIMER_BASE STM32_TIM5_BASE
+# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM5_CLKIN
+#elif defined(CONFIG_STM32_TIM8_ADC2)
+# define ADC2_HAVE_TIMER 1
+# define ADC2_TIMER_BASE STM32_TIM8_BASE
+# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN
+#else
+# undef ADC2_HAVE_TIMER
+#endif
+
+#ifdef ADC2_HAVE_TIMER
+# ifndef CONFIG_STM32_ADC2_SAMPLE_FREQUENCY
+# error "CONFIG_STM32_ADC2_SAMPLE_FREQUENCY not defined"
+# endif
+# ifndef CONFIG_STM32_ADC2_TIMTRIG
+# error "CONFIG_STM32_ADC2_TIMTRIG not defined"
+# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO"
+# endif
+#endif
+
+#if defined(CONFIG_STM32_TIM1_ADC3)
+# define ADC3_HAVE_TIMER 1
+# define ADC3_TIMER_BASE STM32_TIM1_BASE
+# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN
+#elif defined(CONFIG_STM32_TIM2_ADC3)
+# define ADC3_HAVE_TIMER 1
+# define ADC3_TIMER_BASE STM32_TIM2_BASE
+# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN
+#elif defined(CONFIG_STM32_TIM3_ADC3)
+# define ADC3_HAVE_TIMER 1
+# define ADC3_TIMER_BASE STM32_TIM3_BASE
+# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN
+#elif defined(CONFIG_STM32_TIM4_ADC3)
+# define ADC3_HAVE_TIMER 1
+# define ADC3_TIMER_BASE STM32_TIM4_BASE
+# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN
+#elif defined(CONFIG_STM32_TIM5_ADC3)
+# define ADC3_HAVE_TIMER 1
+# define ADC3_TIMER_BASE STM32_TIM5_BASE
+# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM5_CLKIN
+#elif defined(CONFIG_STM32_TIM8_ADC3)
+# define ADC3_HAVE_TIMER 1
+# define ADC3_TIMER_BASE STM32_TIM8_BASE
+# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN
+#else
+# undef ADC3_HAVE_TIMER
+#endif
+
+#ifdef ADC3_HAVE_TIMER
+# ifndef CONFIG_STM32_ADC3_SAMPLE_FREQUENCY
+# error "CONFIG_STM32_ADC3_SAMPLE_FREQUENCY not defined"
+# endif
+# ifndef CONFIG_STM32_ADC3_TIMTRIG
+# error "CONFIG_STM32_ADC3_TIMTRIG not defined"
+# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO"
+# endif
+#endif
+
+#if defined(ADC1_HAVE_TIMER) || defined(ADC2_HAVE_TIMER) || defined(ADC3_HAVE_TIMER)
+# define ADC_HAVE_TIMER 1
+# if defined(CONFIG_STM32_STM32F10XX) && defined(CONFIG_STM32_FORCEPOWER)
+# warning "CONFIG_STM32_FORCEPOWER must be defined to enable the timer(s)"
+# endif
+#else
+# undef ADC_HAVE_TIMER
+#endif
+
+/* NOTE: The following assumes that all possible combinations of timers and
+ * values are support EXTSEL. That is not so and it varies from one STM32 to another.
+ * But this (wrong) assumptions keeps the logic as simple as possible. If un
+ * unsupported combination is used, an error will show up later during compilation
+ * although it may be difficult to track it back to this simplification.
+ */
+
+#if defined(CONFIG_STM32_TIM1_ADC1)
+# if CONFIG_STM32_ADC1_TIMTRIG == 0
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC1
+# elif CONFIG_STM32_ADC1_TIMTRIG == 1
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC2
+# elif CONFIG_STM32_ADC1_TIMTRIG == 2
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC3
+# elif CONFIG_STM32_ADC1_TIMTRIG == 3
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC4
+# elif CONFIG_STM32_ADC1_TIMTRIG == 4
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T1TRGO
+# else
+# error "CONFIG_STM32_ADC1_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM2_ADC1)
+# if CONFIG_STM32_ADC1_TIMTRIG == 0
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC1
+# elif CONFIG_STM32_ADC1_TIMTRIG == 1
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC2
+# elif CONFIG_STM32_ADC1_TIMTRIG == 2
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC3
+# elif CONFIG_STM32_ADC1_TIMTRIG == 3
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC4
+# elif CONFIG_STM32_ADC1_TIMTRIG == 4
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T2TRGO
+# else
+# error "CONFIG_STM32_ADC1_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM3_ADC1)
+# if CONFIG_STM32_ADC1_TIMTRIG == 0
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC1
+# elif CONFIG_STM32_ADC1_TIMTRIG == 1
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC2
+# elif CONFIG_STM32_ADC1_TIMTRIG == 2
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC3
+# elif CONFIG_STM32_ADC1_TIMTRIG == 3
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC4
+# elif CONFIG_STM32_ADC1_TIMTRIG == 4
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T3TRGO
+# else
+# error "CONFIG_STM32_ADC1_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM4_ADC1)
+# if CONFIG_STM32_ADC1_TIMTRIG == 0
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC1
+# elif CONFIG_STM32_ADC1_TIMTRIG == 1
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC2
+# elif CONFIG_STM32_ADC1_TIMTRIG == 2
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC3
+# elif CONFIG_STM32_ADC1_TIMTRIG == 3
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC4
+# elif CONFIG_STM32_ADC1_TIMTRIG == 4
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T4TRGO
+# else
+# error "CONFIG_STM32_ADC1_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM5_ADC1)
+# if CONFIG_STM32_ADC1_TIMTRIG == 0
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC1
+# elif CONFIG_STM32_ADC1_TIMTRIG == 1
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC2
+# elif CONFIG_STM32_ADC1_TIMTRIG == 2
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC3
+# elif CONFIG_STM32_ADC1_TIMTRIG == 3
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC4
+# elif CONFIG_STM32_ADC1_TIMTRIG == 4
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T5TRGO
+# else
+# error "CONFIG_STM32_ADC1_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM8_ADC1)
+# if CONFIG_STM32_ADC1_TIMTRIG == 0
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC1
+# elif CONFIG_STM32_ADC1_TIMTRIG == 1
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC2
+# elif CONFIG_STM32_ADC1_TIMTRIG == 2
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC3
+# elif CONFIG_STM32_ADC1_TIMTRIG == 3
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC4
+# elif CONFIG_STM32_ADC1_TIMTRIG == 4
+# define ADC1_EXTSEL_VALUE ADC_CR2_EXTSEL_T8TRGO
+# else
+# error "CONFIG_STM32_ADC1_TIMTRIG is out of range"
+# endif
+#endif
+
+#if defined(CONFIG_STM32_TIM1_ADC2)
+# if CONFIG_STM32_ADC2_TIMTRIG == 0
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC1
+# elif CONFIG_STM32_ADC2_TIMTRIG == 1
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC2
+# elif CONFIG_STM32_ADC2_TIMTRIG == 2
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC3
+# elif CONFIG_STM32_ADC2_TIMTRIG == 3
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC4
+# elif CONFIG_STM32_ADC2_TIMTRIG == 4
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T1TRGO
+# else
+# error "CONFIG_STM32_ADC2_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM2_ADC2)
+# if CONFIG_STM32_ADC2_TIMTRIG == 0
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC1
+# elif CONFIG_STM32_ADC2_TIMTRIG == 1
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC2
+# elif CONFIG_STM32_ADC2_TIMTRIG == 2
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC3
+# elif CONFIG_STM32_ADC2_TIMTRIG == 3
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC4
+# elif CONFIG_STM32_ADC2_TIMTRIG == 4
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T2TRGO
+# else
+# error "CONFIG_STM32_ADC2_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM3_ADC2)
+# if CONFIG_STM32_ADC2_TIMTRIG == 0
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC1
+# elif CONFIG_STM32_ADC2_TIMTRIG == 1
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC2
+# elif CONFIG_STM32_ADC2_TIMTRIG == 2
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC3
+# elif CONFIG_STM32_ADC2_TIMTRIG == 3
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC4
+# elif CONFIG_STM32_ADC2_TIMTRIG == 4
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T3TRGO
+# else
+# error "CONFIG_STM32_ADC2_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM4_ADC2)
+# if CONFIG_STM32_ADC2_TIMTRIG == 0
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC1
+# elif CONFIG_STM32_ADC2_TIMTRIG == 1
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC2
+# elif CONFIG_STM32_ADC2_TIMTRIG == 2
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC3
+# elif CONFIG_STM32_ADC2_TIMTRIG == 3
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC4
+# elif CONFIG_STM32_ADC2_TIMTRIG == 4
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T4TRGO
+# else
+# error "CONFIG_STM32_ADC2_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM5_ADC2)
+# if CONFIG_STM32_ADC2_TIMTRIG == 0
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC1
+# elif CONFIG_STM32_ADC2_TIMTRIG == 1
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC2
+# elif CONFIG_STM32_ADC2_TIMTRIG == 2
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC3
+# elif CONFIG_STM32_ADC2_TIMTRIG == 3
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC4
+# elif CONFIG_STM32_ADC2_TIMTRIG == 4
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T5TRGO
+# else
+# error "CONFIG_STM32_ADC2_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM8_ADC2)
+# if CONFIG_STM32_ADC2_TIMTRIG == 0
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC1
+# elif CONFIG_STM32_ADC2_TIMTRIG == 1
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC2
+# elif CONFIG_STM32_ADC2_TIMTRIG == 2
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC3
+# elif CONFIG_STM32_ADC2_TIMTRIG == 3
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC4
+# elif CONFIG_STM32_ADC2_TIMTRIG == 4
+# define ADC2_EXTSEL_VALUE ADC_CR2_EXTSEL_T8TRGO
+# else
+# error "CONFIG_STM32_ADC2_TIMTRIG is out of range"
+# endif
+#endif
+
+#if defined(CONFIG_STM32_TIM1_ADC3)
+# if CONFIG_STM32_ADC3_TIMTRIG == 0
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC1
+# elif CONFIG_STM32_ADC3_TIMTRIG == 1
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC2
+# elif CONFIG_STM32_ADC3_TIMTRIG == 2
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC3
+# elif CONFIG_STM32_ADC3_TIMTRIG == 3
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1CC4
+# elif CONFIG_STM32_ADC3_TIMTRIG == 4
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T1TRGO
+# else
+# error "CONFIG_STM32_ADC3_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM2_ADC3)
+# if CONFIG_STM32_ADC3_TIMTRIG == 0
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC1
+# elif CONFIG_STM32_ADC3_TIMTRIG == 1
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC2
+# elif CONFIG_STM32_ADC3_TIMTRIG == 2
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC3
+# elif CONFIG_STM32_ADC3_TIMTRIG == 3
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2CC4
+# elif CONFIG_STM32_ADC3_TIMTRIG == 4
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T2TRGO
+# else
+# error "CONFIG_STM32_ADC3_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM3_ADC3)
+# if CONFIG_STM32_ADC3_TIMTRIG == 0
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC1
+# elif CONFIG_STM32_ADC3_TIMTRIG == 1
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC2
+# elif CONFIG_STM32_ADC3_TIMTRIG == 2
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC3
+# elif CONFIG_STM32_ADC3_TIMTRIG == 3
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3CC4
+# elif CONFIG_STM32_ADC3_TIMTRIG == 4
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T3TRGO
+# else
+# error "CONFIG_STM32_ADC3_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM4_ADC3)
+# if CONFIG_STM32_ADC3_TIMTRIG == 0
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC1
+# elif CONFIG_STM32_ADC3_TIMTRIG == 1
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC2
+# elif CONFIG_STM32_ADC3_TIMTRIG == 2
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC3
+# elif CONFIG_STM32_ADC3_TIMTRIG == 3
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4CC4
+# elif CONFIG_STM32_ADC3_TIMTRIG == 4
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T4TRGO
+# else
+# error "CONFIG_STM32_ADC3_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM5_ADC3)
+# if CONFIG_STM32_ADC3_TIMTRIG == 0
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC1
+# elif CONFIG_STM32_ADC3_TIMTRIG == 1
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC2
+# elif CONFIG_STM32_ADC3_TIMTRIG == 2
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC3
+# elif CONFIG_STM32_ADC3_TIMTRIG == 3
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5CC4
+# elif CONFIG_STM32_ADC3_TIMTRIG == 4
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T5TRGO
+# else
+# error "CONFIG_STM32_ADC3_TIMTRIG is out of range"
+# endif
+#elif defined(CONFIG_STM32_TIM8_ADC3)
+# if CONFIG_STM32_ADC3_TIMTRIG == 0
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC1
+# elif CONFIG_STM32_ADC3_TIMTRIG == 1
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC2
+# elif CONFIG_STM32_ADC3_TIMTRIG == 2
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC3
+# elif CONFIG_STM32_ADC3_TIMTRIG == 3
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8CC4
+# elif CONFIG_STM32_ADC3_TIMTRIG == 4
+# define ADC3_EXTSEL_VALUE ADC_CR2_EXTSEL_T8TRGO
+# else
+# error "CONFIG_STM32_ADC3_TIMTRIG is out of range"
+# endif
+#endif
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: stm32_adcinitialize
+ *
+ * Description:
+ * Initialize the ADC.
+ *
+ * Input Parameters:
+ * intf - Could be {1,2,3} for ADC1, ADC2, or ADC3
+ * chanlist - The list of channels
+ * nchannels - Number of channels
+ *
+ * Returned Value:
+ * Valid can device structure reference on succcess; a NULL on failure
+ *
+ ****************************************************************************/
+
+struct adc_dev_s;
+EXTERN struct adc_dev_s *stm32_adcinitialize(int intf, const uint8_t *chanlist,
+ int nchannels);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_STM32_ADC || CONFIG_STM32_ADC2 || CONFIG_STM32_ADC3 */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_ADC_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_allocateheap.c b/nuttx/arch/arm/src/stm32/stm32_allocateheap.c
new file mode 100644
index 000000000..4c186a852
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_allocateheap.c
@@ -0,0 +1,323 @@
+/****************************************************************************
+ * arch/arm/src/stm32/up_allocateheap.c
+ *
+ * Copyright (C) 2011-2012 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 <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/mm.h>
+
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "up_arch.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Private Definitions
+ ****************************************************************************/
+/* Internal SRAM is available in all members of the STM32 family. The
+ * following definitions must be provided to specify the size and
+ * location of internal(system) SRAM:
+ *
+ * CONFIG_DRAM_END : End address (+1) of SRAM (F1 family only, the
+ * : F4 family uses the a priori end of SRAM)
+ *
+ * The F4 family also contains internal CCM SRAM. This SRAM is different
+ * because it cannot be used for DMA. So if DMA needed, then the following
+ * should be defined to exclude CCM SRAM from the heap:
+ *
+ * CONFIG_STM32_CCMEXCLUDE : Exclude CCM SRAM from the HEAP
+ *
+ * In addition to internal SRAM, SRAM may also be available through the FSMC.
+ * In order to use FSMC SRAM, the following additional things need to be
+ * present in the NuttX configuration file:
+ *
+ * CONFIG_STM32_FSMC=y : Enables the FSMC
+ * CONFIG_STM32_FSMC_SRAM=y : Indicates that SRAM is available via the
+ * FSMC (as opposed to an LCD or FLASH).
+ * CONFIG_HEAP2_BASE : The base address of the SRAM in the FSMC
+ * address space
+ * CONFIG_HEAP2_END : The end (+1) of the SRAM in the FSMC
+ * address space
+ * CONFIG_MM_REGIONS : Must be set to a large enough value to
+ * include the FSMC SRAM (as determined by the rules provided below)
+ */
+
+#ifndef CONFIG_STM32_FSMC
+# undef CONFIG_STM32_FSMC_SRAM
+#endif
+
+/* For the STM312F10xxx family, all internal SRAM is in one contiguous block
+ * starting at g_heapbase and extending through CONFIG_DRAM_END (my apologies for
+ * the bad naming). In addition, external FSMC SRAM may be available.
+ */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+
+ /* Set the end of system SRAM */
+
+# define SRAM1_END CONFIG_DRAM_END
+
+ /* Check if external FSMC SRAM is provided */
+
+# if CONFIG_STM32_FSMC_SRAM
+# if CONFIG_MM_REGIONS < 2
+# warning "FSMC SRAM not included in the heap"
+# undef CONFIG_STM32_FSMC_SRAM
+# elif CONFIG_MM_REGIONS > 2
+# error "CONFIG_MM_REGIONS > 2 but I don't know what some of the region(s) are"
+# undef CONFIG_MM_REGIONS
+# define CONFIG_MM_REGIONS 2
+# endif
+# elif CONFIG_MM_REGIONS > 1
+# error "CONFIG_MM_REGIONS > 1 but I don't know what the other region(s) are"
+# endif
+
+ /* The STM32 F1 has no CCM SRAM */
+
+# undef CONFIG_STM32_CCMEXCLUDE
+# define CONFIG_STM32_CCMEXCLUDE 1
+
+/* All members of the STM32F20xxx and STM32F40xxx families have 192Kb in three banks:
+ *
+ * 1) 112Kb of System SRAM beginning at address 0x2000:0000
+ * 2) 16Kb of System SRAM beginning at address 0x2001:c000
+ * 3) 64Kb of CCM SRAM beginning at address 0x1000:0000
+ *
+ * As determined by ld.script, g_heapbase lies in the 112Kb memory
+ * region and that extends to 0x2001:0000. But the first and second memory
+ * regions are contiguous and treated as one in this logic that extends to
+ * 0x2002:0000.
+ *
+ * As a complication, it appears that CCM SRAM cannot be used for DMA. So, if
+ * STM32 DMA is enabled, CCM SRAM should probably be excluded from the heap.
+ *
+ * In addition, external FSMC SRAM may be available.
+ */
+
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+
+
+ /* The STM32 F2 has no CCM SRAM */
+
+# ifdef CONFIG_STM32_STM32F20XX
+# undef CONFIG_STM32_CCMEXCLUDE
+# define CONFIG_STM32_CCMEXCLUDE 1
+# endif
+
+ /* Set the end of system SRAM */
+
+# define SRAM1_END 0x20020000
+
+ /* Set the range of CCM SRAM as well (although we may not use it) */
+
+# define SRAM2_START 0x10000000
+# define SRAM2_END 0x10010000
+
+ /* There are 4 possible SRAM configurations:
+ *
+ * Configuration 1. System SRAM (only)
+ * CONFIG_MM_REGIONS == 1
+ * CONFIG_STM32_FSMC_SRAM NOT defined
+ * CONFIG_STM32_CCMEXCLUDE defined
+ * Configuration 2. System SRAM and CCM SRAM
+ * CONFIG_MM_REGIONS == 2
+ * CONFIG_STM32_FSMC_SRAM NOT defined
+ * CONFIG_STM32_CCMEXCLUDE NOT defined
+ * Configuration 3. System SRAM and FSMC SRAM
+ * CONFIG_MM_REGIONS == 2
+ * CONFIG_STM32_FSMC_SRAM defined
+ * CONFIG_STM32_CCMEXCLUDE defined
+ * Configuration 4. System SRAM, CCM SRAM, and FSMC SRAM
+ * CONFIG_MM_REGIONS == 3
+ * CONFIG_STM32_FSMC_SRAM defined
+ * CONFIG_STM32_CCMEXCLUDE NOT defined
+ *
+ * Let's make sure that all definitions are consitent before doing
+ * anything else
+ */
+
+# if defined(CONFIG_STM32_FSMC_SRAM)
+
+ /* Configuration 3 or 4. External SRAM is available. CONFIG_MM_REGIONS
+ * should be at least 2.
+ */
+
+# if CONFIG_MM_REGIONS < 2
+ /* Only one memory region. Force Configuration 1 */
+
+# warning "FSMC SRAM (and CCM SRAM) excluded from the heap"
+# undef CONFIG_STM32_FSMC_SRAM
+# undef CONFIG_STM32_CCMEXCLUDE
+# define CONFIG_STM32_CCMEXCLUDE 1
+
+ /* CONFIG_MM_REGIONS may be 3 if CCM SRAM is included in the head */
+
+# elif CONFIG_MM_REGIONS > 2
+
+ /* More than two memory regions. This is okay if CCM SRAM is not
+ * disabled.
+ */
+
+# if defined(CONFIG_STM32_CCMEXCLUDE)
+
+ /* Configuration 3: CONFIG_MM_REGIONS should have been 2 */
+
+# error "CONFIG_MM_REGIONS > 2 but I don't know what some of the region(s) are"
+# undef CONFIG_MM_REGIONS
+# define CONFIG_MM_REGIONS 2
+# else
+
+ /* Configuration 4: DMA should be disabled and CONFIG_MM_REGIONS
+ * should be 3.
+ */
+
+# ifdef CONFIG_STM32_DMA
+# warning "CCM SRAM is included in the heap AND DMA is enabled"
+# endif
+# if CONFIG_MM_REGIONS != 3
+# error "CONFIG_MM_REGIONS > 3 but I don't know what some of the region(s) are"
+# undef CONFIG_MM_REGIONS
+# define CONFIG_MM_REGIONS 3
+# endif
+# endif
+
+ /* CONFIG_MM_REGIONS is exactly 2. We cannot support both CCM SRAM and
+ * FSMC SRAM.
+ */
+
+# elif !defined(CONFIG_STM32_CCMEXCLUDE)
+# error "CONFIG_MM_REGIONS == 2, cannot support both CCM SRAM and FSMC SRAM"
+# undef CONFIG_STM32_CCMEXCLUDE
+# define CONFIG_STM32_CCMEXCLUDE 1
+# endif
+
+# elif !defined(CONFIG_STM32_CCMEXCLUDE)
+
+ /* Configuration 2: FSMC SRAM is not used, but CCM SRAM is requested. DMA
+ * should be disabled and CONFIG_MM_REGIONS should be 2.
+ */
+
+# ifdef CONFIG_STM32_DMA
+# warning "CCM SRAM is included in the heap AND DMA is enabled"
+# endif
+# if CONFIG_MM_REGIONS < 2
+# error "CCM SRAM excluded from the heap because CONFIG_MM_REGIONS < 2"
+# undef CONFIG_STM32_CCMEXCLUDE
+# define CONFIG_STM32_CCMEXCLUDE 1
+# elif CONFIG_MM_REGIONS > 2
+# error "CONFIG_MM_REGIONS > 2 but I don't know what some of the region(s) are"
+# undef CONFIG_MM_REGIONS
+# define CONFIG_MM_REGIONS 2
+# endif
+# endif
+#else
+# error "Unsupported STM32 chip"
+#endif
+
+/* If FSMC SRAM is going to be used as heap, then verify that the starting
+ * address and size of the external SRAM region has been provided in the
+ * configuration (as CONFIG_HEAP2_BASE and CONFIG_HEAP2_END).
+ */
+
+#ifdef CONFIG_STM32_FSMC_SRAM
+# if !defined(CONFIG_HEAP2_BASE) || !defined(CONFIG_HEAP2_END)
+# error "CONFIG_HEAP2_BASE and CONFIG_HEAP2_END must be provided"
+# undef CONFIG_STM32_FSMC_SRAM
+# endif
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocate_heap
+ *
+ * Description:
+ * The heap may be statically allocated by
+ * defining CONFIG_HEAP_BASE and CONFIG_HEAP_SIZE. If these
+ * are not defined, then this function will be called to
+ * dynamically set aside the heap region.
+ *
+ ****************************************************************************/
+
+void up_allocate_heap(FAR void **heap_start, size_t *heap_size)
+{
+ up_ledon(LED_HEAPALLOCATE);
+ *heap_start = (FAR void*)g_heapbase;
+ *heap_size = SRAM1_END - g_heapbase;
+}
+
+/****************************************************************************
+ * Name: up_addregion
+ *
+ * Description:
+ * Memory may be added in non-contiguous chunks. Additional chunks are
+ * added by calling this function.
+ *
+ ****************************************************************************/
+
+#if CONFIG_MM_REGIONS > 1
+void up_addregion(void)
+{
+ /* Add the STM32F20xxx/STM32F40xxx CCM SRAM heap region. */
+
+#ifndef CONFIG_STM32_CCMEXCLUDE
+ mm_addregion((FAR void*)SRAM2_START, SRAM2_END-SRAM2_START);
+#endif
+
+ /* Add the external FSMC SRAM heap region. */
+
+#ifdef CONFIG_STM32_FSMC_SRAM
+ mm_addregion((FAR void*)CONFIG_HEAP2_BASE, CONFIG_HEAP2_END - CONFIG_HEAP2_BASE);
+#endif
+}
+#endif
diff --git a/nuttx/arch/arm/src/stm32/stm32_bkp.h b/nuttx/arch/arm/src/stm32/stm32_bkp.h
new file mode 100644
index 000000000..21399c38b
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_bkp.h
@@ -0,0 +1,52 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_bkp.h
+ *
+ * Copyright (C) 2009, 2012 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_STM32_STM32_BKP_H
+#define __ARCH_ARM_SRC_STM32_STM32_BKP_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_bkp.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_STM32_STM32_BKP_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_can.c b/nuttx/arch/arm/src/stm32/stm32_can.c
new file mode 100644
index 000000000..bed2a80f6
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_can.c
@@ -0,0 +1,1636 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_can.c
+ *
+ * Copyright (C) 2011 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 <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+#include <nuttx/arch.h>
+#include <nuttx/can.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "os_internal.h"
+
+#include "chip.h"
+#include "stm32_internal.h"
+#include "stm32_can.h"
+
+#if defined(CONFIG_CAN) && (defined(CONFIG_STM32_CAN1) || defined(CONFIG_STM32_CAN2))
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Delays *******************************************************************/
+/* Time out for INAK bit */
+
+#define INAK_TIMEOUT 65535
+
+/* Mailboxes ****************************************************************/
+
+#define CAN_ALL_MAILBOXES (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2)
+
+/* Bit timing ***************************************************************/
+
+#define CAN_BIT_QUANTA (CONFIG_CAN_TSEG1 + CONFIG_CAN_TSEG2 + 1)
+
+/* Debug ********************************************************************/
+/* Non-standard debug that may be enabled just for testing CAN */
+
+#ifdef CONFIG_DEBUG_CAN
+# define candbg dbg
+# define canvdbg vdbg
+# define canlldbg lldbg
+# define canllvdbg llvdbg
+#else
+# define candbg(x...)
+# define canvdbg(x...)
+# define canlldbg(x...)
+# define canllvdbg(x...)
+#endif
+
+#if !defined(CONFIG_DEBUG) || !defined(CONFIG_DEBUG_CAN)
+# undef CONFIG_CAN_REGDEBUG
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct stm32_can_s
+{
+ uint8_t port; /* CAN port number (1 or 2) */
+ uint8_t canrx0; /* CAN RX FIFO 0 IRQ number */
+ uint8_t cantx; /* CAN TX IRQ number */
+ uint8_t filter; /* Filter number */
+ uint32_t base; /* Base address of the CAN registers */
+ uint32_t baud; /* Configured baud */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* CAN Register access */
+
+static uint32_t can_getreg(struct stm32_can_s *priv, int offset);
+static void can_putreg(struct stm32_can_s *priv, int offset, uint32_t value);
+#ifdef CONFIG_CAN_REGDEBUG
+static void can_dumpctrlregs(struct stm32_can_s *priv, FAR const char *msg);
+static void can_dumpmbregs(struct stm32_can_s *priv, FAR const char *msg);
+static void can_dumpfiltregs(struct stm32_can_s *priv, FAR const char *msg);
+#else
+# define can_dumpctrlregs(priv,msg)
+# define can_dumpmbregs(priv,msg)
+# define can_dumpfiltregs(priv,msg)
+#endif
+
+/* CAN driver methods */
+
+static void can_reset(FAR struct can_dev_s *dev);
+static int can_setup(FAR struct can_dev_s *dev);
+static void can_shutdown(FAR struct can_dev_s *dev);
+static void can_rxint(FAR struct can_dev_s *dev, bool enable);
+static void can_txint(FAR struct can_dev_s *dev, bool enable);
+static int can_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg);
+static int can_remoterequest(FAR struct can_dev_s *dev, uint16_t id);
+static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg);
+static bool can_txready(FAR struct can_dev_s *dev);
+static bool can_txempty(FAR struct can_dev_s *dev);
+
+/* CAN interrupt handling */
+
+static int can_rx0interrupt(int irq, void *context);
+static int can_txinterrupt(int irq, void *context);
+
+/* Initialization */
+
+static int can_bittiming(struct stm32_can_s *priv);
+static int can_cellinit(struct stm32_can_s *priv);
+static int can_filterinit(struct stm32_can_s *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct can_ops_s g_canops =
+{
+ .co_reset = can_reset,
+ .co_setup = can_setup,
+ .co_shutdown = can_shutdown,
+ .co_rxint = can_rxint,
+ .co_txint = can_txint,
+ .co_ioctl = can_ioctl,
+ .co_remoterequest = can_remoterequest,
+ .co_send = can_send,
+ .co_txready = can_txready,
+ .co_txempty = can_txempty,
+};
+
+#ifdef CONFIG_STM32_CAN1
+static struct stm32_can_s g_can1priv =
+{
+ .port = 1,
+#if defined(CONFIG_STM32_STM32F10XX) && !defined(CONFIG_STM32_CONNECTIVITYLINE)
+ .canrx0 = STM32_IRQ_USBLPCANRX0,
+ .cantx = STM32_IRQ_USBHPCANTX,
+#else
+ .canrx0 = STM32_IRQ_CAN1RX0,
+ .cantx = STM32_IRQ_CAN1TX,
+#endif
+ .filter = 0,
+ .base = STM32_CAN1_BASE,
+ .baud = CONFIG_CAN1_BAUD,
+};
+
+static struct can_dev_s g_can1dev =
+{
+ .cd_ops = &g_canops,
+ .cd_priv = &g_can1priv,
+};
+#endif
+
+#ifdef CONFIG_STM32_CAN2
+static struct stm32_can_s g_can2priv =
+{
+ .port = 2,
+ .canrx0 = STM32_IRQ_CAN2RX0,
+ .cantx = STM32_IRQ_CAN2TX,
+ .filter = CAN_NFILTERS / 2,
+ .base = STM32_CAN2_BASE,
+ .baud = CONFIG_CAN2_BAUD,
+};
+
+static struct can_dev_s g_can2dev =
+{
+ .cd_ops = &g_canops,
+ .cd_priv = &g_can2priv,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_getreg
+ *
+ * Description:
+ * Read the value of an CAN register.
+ *
+ * Input Parameters:
+ * priv - A reference to the CAN block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_CAN_REGDEBUG
+static uint32_t can_getreg(struct stm32_can_s *priv, int offset)
+{
+ static uint32_t prevaddr = 0;
+ static uint32_t preval = 0;
+ static uint32_t count = 0;
+ uint32_t addr = priv->base + offset;
+
+ /* Read the value from the register */
+
+ uint32_t val = getreg32(addr);
+
+ /* Is this the same value that we read from the same register last time?
+ * Are we polling the register? If so, suppress some of the output.
+ */
+
+ if (addr == prevaddr && val == preval)
+ {
+ if (count == 0xffffffff || ++count > 3)
+ {
+ if (count == 4)
+ {
+ lldbg("...\n");
+ }
+ return val;
+ }
+ }
+
+ /* No this is a new address or value */
+
+ else
+ {
+ /* Did we print "..." for the previous value? */
+
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
+
+ lldbg("[repeats %d more times]\n", count-3);
+ }
+
+ /* Save the new address, value, and count */
+
+ prevaddr = addr;
+ preval = val;
+ count = 1;
+ }
+
+ /* Show the register value read */
+
+ lldbg("%08x->%08x\n", addr, val);
+ return val;
+}
+#else
+static uint32_t can_getreg(struct stm32_can_s *priv, int offset)
+{
+ return getreg32(priv->base + offset);
+}
+#endif
+
+/****************************************************************************
+ * Name: can_putreg
+ *
+ * Description:
+ * Set the value of an CAN register.
+ *
+ * Input Parameters:
+ * priv - A reference to the CAN block status
+ * offset - The offset to the register to write
+ * value - The value to write to the register
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_CAN_REGDEBUG
+static void can_putreg(struct stm32_can_s *priv, int offset, uint32_t value)
+{
+ uint32_t addr = priv->base + offset;
+
+ /* Show the register value being written */
+
+ lldbg("%08x<-%08x\n", addr, value);
+
+ /* Write the value */
+
+ putreg32(value, addr);
+}
+#else
+static void can_putreg(struct stm32_can_s *priv, int offset, uint32_t value)
+{
+ putreg32(value, priv->base + offset);
+}
+#endif
+
+/****************************************************************************
+ * Name: can_dumpctrlregs
+ *
+ * Description:
+ * Dump the contents of all CAN control registers
+ *
+ * Input Parameters:
+ * priv - A reference to the CAN block status
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_CAN_REGDEBUG
+static void can_dumpctrlregs(struct stm32_can_s *priv, FAR const char *msg)
+{
+ if (msg)
+ {
+ canlldbg("Control Registers: %s\n", msg);
+ }
+ else
+ {
+ canlldbg("Control Registers:\n");
+ }
+
+ /* CAN control and status registers */
+
+ lldbg(" MCR: %08x MSR: %08x TSR: %08x\n",
+ getreg32(priv->base + STM32_CAN_MCR_OFFSET),
+ getreg32(priv->base + STM32_CAN_MSR_OFFSET),
+ getreg32(priv->base + STM32_CAN_TSR_OFFSET));
+
+ lldbg(" RF0R: %08x RF1R: %08x\n",
+ getreg32(priv->base + STM32_CAN_RF0R_OFFSET),
+ getreg32(priv->base + STM32_CAN_RF1R_OFFSET));
+
+ lldbg(" IER: %08x ESR: %08x BTR: %08x\n",
+ getreg32(priv->base + STM32_CAN_IER_OFFSET),
+ getreg32(priv->base + STM32_CAN_ESR_OFFSET),
+ getreg32(priv->base + STM32_CAN_BTR_OFFSET));
+}
+#endif
+
+/****************************************************************************
+ * Name: can_dumpmbregs
+ *
+ * Description:
+ * Dump the contents of all CAN mailbox registers
+ *
+ * Input Parameters:
+ * priv - A reference to the CAN block status
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_CAN_REGDEBUG
+static void can_dumpmbregs(struct stm32_can_s *priv, FAR const char *msg)
+{
+ if (msg)
+ {
+ canlldbg("Mailbox Registers: %s\n", msg);
+ }
+ else
+ {
+ canlldbg("Mailbox Registers:\n");
+ }
+
+ /* CAN mailbox registers (3 TX and 2 RX) */
+
+ lldbg(" TI0R: %08x TDT0R: %08x TDL0R: %08x TDH0R: %08x\n",
+ getreg32(priv->base + STM32_CAN_TI0R_OFFSET),
+ getreg32(priv->base + STM32_CAN_TDT0R_OFFSET),
+ getreg32(priv->base + STM32_CAN_TDL0R_OFFSET),
+ getreg32(priv->base + STM32_CAN_TDH0R_OFFSET));
+
+ lldbg(" TI1R: %08x TDT1R: %08x TDL1R: %08x TDH1R: %08x\n",
+ getreg32(priv->base + STM32_CAN_TI1R_OFFSET),
+ getreg32(priv->base + STM32_CAN_TDT1R_OFFSET),
+ getreg32(priv->base + STM32_CAN_TDL1R_OFFSET),
+ getreg32(priv->base + STM32_CAN_TDH1R_OFFSET));
+
+ lldbg(" TI2R: %08x TDT2R: %08x TDL2R: %08x TDH2R: %08x\n",
+ getreg32(priv->base + STM32_CAN_TI2R_OFFSET),
+ getreg32(priv->base + STM32_CAN_TDT2R_OFFSET),
+ getreg32(priv->base + STM32_CAN_TDL2R_OFFSET),
+ getreg32(priv->base + STM32_CAN_TDH2R_OFFSET));
+
+ lldbg(" RI0R: %08x RDT0R: %08x RDL0R: %08x RDH0R: %08x\n",
+ getreg32(priv->base + STM32_CAN_RI0R_OFFSET),
+ getreg32(priv->base + STM32_CAN_RDT0R_OFFSET),
+ getreg32(priv->base + STM32_CAN_RDL0R_OFFSET),
+ getreg32(priv->base + STM32_CAN_RDH0R_OFFSET));
+
+ lldbg(" RI1R: %08x RDT1R: %08x RDL1R: %08x RDH1R: %08x\n",
+ getreg32(priv->base + STM32_CAN_RI1R_OFFSET),
+ getreg32(priv->base + STM32_CAN_RDT1R_OFFSET),
+ getreg32(priv->base + STM32_CAN_RDL1R_OFFSET),
+ getreg32(priv->base + STM32_CAN_RDH1R_OFFSET));
+}
+#endif
+
+/****************************************************************************
+ * Name: can_dumpfiltregs
+ *
+ * Description:
+ * Dump the contents of all CAN filter registers
+ *
+ * Input Parameters:
+ * priv - A reference to the CAN block status
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_CAN_REGDEBUG
+static void can_dumpfiltregs(struct stm32_can_s *priv, FAR const char *msg)
+{
+ int i;
+
+ if (msg)
+ {
+ canlldbg("Filter Registers: %s\n", msg);
+ }
+ else
+ {
+ canlldbg("Filter Registers:\n");
+ }
+
+ lldbg(" FMR: %08x FM1R: %08x FS1R: %08x FFA1R: %08x FA1R: %08x\n",
+ getreg32(priv->base + STM32_CAN_FMR_OFFSET),
+ getreg32(priv->base + STM32_CAN_FM1R_OFFSET),
+ getreg32(priv->base + STM32_CAN_FS1R_OFFSET),
+ getreg32(priv->base + STM32_CAN_FFA1R_OFFSET),
+ getreg32(priv->base + STM32_CAN_FA1R_OFFSET));
+
+ for (i = 0; i < CAN_NFILTERS; i++)
+ {
+ lldbg(" F%dR1: %08x F%dR2: %08x\n",
+ i, getreg32(priv->base + STM32_CAN_FR_OFFSET(i,1)),
+ i, getreg32(priv->base + STM32_CAN_FR_OFFSET(i,2)));
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: can_reset
+ *
+ * Description:
+ * Reset the CAN device. Called early to initialize the hardware. This
+ * function is called, before can_setup() and on error conditions.
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void can_reset(FAR struct can_dev_s *dev)
+{
+ FAR struct stm32_can_s *priv = dev->cd_priv;
+ uint32_t regval;
+ uint32_t regbit = 0;
+ irqstate_t flags;
+
+ canllvdbg("CAN%d\n", priv->port);
+
+ /* Get the bits in the AHB1RSTR register needed to reset this CAN device */
+
+#ifdef CONFIG_STM32_CAN1
+ if (priv->port == 1)
+ {
+ regbit = RCC_APB1RSTR_CAN1RST;
+ }
+ else
+#endif
+#ifdef CONFIG_STM32_CAN2
+ if (priv->port == 2)
+ {
+ regbit = RCC_APB1RSTR_CAN2RST;
+ }
+ else
+#endif
+ {
+ canlldbg("Unsupported port %d\n", priv->port);
+ return;
+ }
+
+ /* Disable interrupts momentary to stop any ongoing CAN event processing and
+ * to prevent any concurrent access to the AHB1RSTR register.
+ */
+
+ flags = irqsave();
+
+ /* Reset the CAN */
+
+ regval = getreg32(STM32_RCC_APB1RSTR);
+ regval |= regbit;
+ putreg32(regval, STM32_RCC_APB1RSTR);
+
+ regval &= ~regbit;
+ putreg32(regval, STM32_RCC_APB1RSTR);
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: can_setup
+ *
+ * Description:
+ * Configure the CAN. This method is called the first time that the CAN
+ * device is opened. This will occur when the port is first opened.
+ * This setup includes configuring and attaching CAN interrupts.
+ * All CAN interrupts are disabled upon return.
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int can_setup(FAR struct can_dev_s *dev)
+{
+ FAR struct stm32_can_s *priv = dev->cd_priv;
+ int ret;
+
+ canllvdbg("CAN%d RX0 irq: %d TX irq: %d\n", priv->port, priv->canrx0, priv->cantx);
+
+ /* CAN cell initialization */
+
+ ret = can_cellinit(priv);
+ if (ret < 0)
+ {
+ canlldbg("CAN%d cell initialization failed: %d\n", priv->port, ret);
+ return ret;
+ }
+
+ can_dumpctrlregs(priv, "After cell initialization");
+ can_dumpmbregs(priv, NULL);
+
+ /* CAN filter initialization */
+
+ ret = can_filterinit(priv);
+ if (ret < 0)
+ {
+ canlldbg("CAN%d filter initialization failed: %d\n", priv->port, ret);
+ return ret;
+ }
+ can_dumpfiltregs(priv, "After filter initialization");
+
+ /* Attach the CAN RX FIFO 0 interrupt and TX interrupts. The others are not used */
+
+ ret = irq_attach(priv->canrx0, can_rx0interrupt);
+ if (ret < 0)
+ {
+ canlldbg("Failed to attach CAN%d RX0 IRQ (%d)", priv->port, priv->canrx0);
+ return ret;
+ }
+
+ ret = irq_attach(priv->cantx, can_txinterrupt);
+ if (ret < 0)
+ {
+ canlldbg("Failed to attach CAN%d TX IRQ (%d)", priv->port, priv->cantx);
+ return ret;
+ }
+
+ /* Enable the interrupts at the NVIC. Interrupts arestill disabled in
+ * the CAN module. Since we coming out of reset here, there should be
+ * no pending interrupts.
+ */
+
+ up_enable_irq(priv->canrx0);
+ up_enable_irq(priv->cantx);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: can_shutdown
+ *
+ * Description:
+ * Disable the CAN. This method is called when the CAN device is closed.
+ * This method reverses the operation the setup method.
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void can_shutdown(FAR struct can_dev_s *dev)
+{
+ FAR struct stm32_can_s *priv = dev->cd_priv;
+
+ canllvdbg("CAN%d\n", priv->port);
+
+ /* Disable the RX FIFO 0 and TX interrupts */
+
+ up_disable_irq(priv->canrx0);
+ up_disable_irq(priv->cantx);
+
+ /* Detach the RX FIFO 0 and TX interrupts */
+
+ irq_detach(priv->canrx0);
+ irq_detach(priv->cantx);
+
+ /* And reset the hardware */
+
+ can_reset(dev);
+}
+
+/****************************************************************************
+ * Name: can_rxint
+ *
+ * Description:
+ * Call to enable or disable RX interrupts.
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void can_rxint(FAR struct can_dev_s *dev, bool enable)
+{
+ FAR struct stm32_can_s *priv = dev->cd_priv;
+ uint32_t regval;
+
+ canllvdbg("CAN%d enable: %d\n", priv->port, enable);
+
+ /* Enable/disable the FIFO 0 message pending interrupt */
+
+ regval = can_getreg(priv, STM32_CAN_IER_OFFSET);
+ if (enable)
+ {
+ regval |= CAN_IER_FMPIE0;
+ }
+ else
+ {
+ regval &= ~CAN_IER_FMPIE0;
+ }
+ can_putreg(priv, STM32_CAN_IER_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: can_txint
+ *
+ * Description:
+ * Call to enable or disable TX interrupts.
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void can_txint(FAR struct can_dev_s *dev, bool enable)
+{
+ FAR struct stm32_can_s *priv = dev->cd_priv;
+ uint32_t regval;
+
+ canllvdbg("CAN%d enable: %d\n", priv->port, enable);
+
+ /* Support only disabling the transmit mailbox interrupt */
+
+ if (!enable)
+ {
+ regval = can_getreg(priv, STM32_CAN_IER_OFFSET);
+ regval &= ~CAN_IER_TMEIE;
+ can_putreg(priv, STM32_CAN_IER_OFFSET, regval);
+ }
+}
+
+/****************************************************************************
+ * Name: can_ioctl
+ *
+ * Description:
+ * All ioctl calls will be routed through this method
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int can_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg)
+{
+ /* No CAN ioctls are supported */
+
+ return -ENOTTY;
+}
+
+/****************************************************************************
+ * Name: can_remoterequest
+ *
+ * Description:
+ * Send a remote request
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int can_remoterequest(FAR struct can_dev_s *dev, uint16_t id)
+{
+#warning "Remote request not implemented"
+ return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: can_send
+ *
+ * Description:
+ * Send one can message.
+ *
+ * One CAN-message consists of a maximum of 10 bytes. A message is
+ * composed of at least the first 2 bytes (when there are no data bytes).
+ *
+ * Byte 0: Bits 0-7: Bits 3-10 of the 11-bit CAN identifier
+ * Byte 1: Bits 5-7: Bits 0-2 of the 11-bit CAN identifier
+ * Bit 4: Remote Tranmission Request (RTR)
+ * Bits 0-3: Data Length Code (DLC)
+ * Bytes 2-10: CAN data
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
+{
+ FAR struct stm32_can_s *priv = dev->cd_priv;
+ FAR uint8_t *ptr;
+ uint32_t regval;
+ uint32_t tmp;
+ int dlc;
+ int txmb;
+
+ canllvdbg("CAN%d ID: %d DLC: %d\n", priv->port, msg->cm_hdr.ch_id, msg->cm_hdr.ch_dlc);
+
+ /* Select one empty transmit mailbox */
+
+ regval = can_getreg(priv, STM32_CAN_TSR_OFFSET);
+ if ((regval & CAN_TSR_TME0) != 0)
+ {
+ txmb = 0;
+ }
+ else if ((regval & CAN_TSR_TME1) != 0)
+ {
+ txmb = 1;
+ }
+ else if ((regval & CAN_TSR_TME2) != 0)
+ {
+ txmb = 2;
+ }
+ else
+ {
+ canlldbg("ERROR: No available mailbox\n");
+ return -EBUSY;
+ }
+
+ /* Clear TXRQ, RTR, IDE, EXID, and STID fields */
+
+ regval = can_getreg(priv, STM32_CAN_TIR_OFFSET(txmb));
+ regval &= ~(CAN_TIR_TXRQ | CAN_TIR_RTR | CAN_TIR_IDE | CAN_TIR_EXID_MASK | CAN_TIR_STID_MASK);
+ can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval);
+
+ /* Set up the ID, standard 11-bit or extended 29-bit. */
+
+#ifdef CONFIG_CAN_EXTID
+ regval &= ~CAN_TIR_EXID_MASK;
+ if (msg->cm_hdr.ch_extid)
+ {
+ DEBUGASSERT(msg->cm_hdr.ch_id < (1 << 29));
+ regval |= (msg->cm_hdr.ch_id << CAN_TIR_EXID_SHIFT) | CAN_TIR_IDE;
+ }
+ else
+ {
+ DEBUGASSERT(msg->cm_hdr.ch_id < (1 << 11));
+ regval |= msg->cm_hdr.ch_id << CAN_TIR_STID_SHIFT;
+ }
+#else
+ regval &= ~CAN_TIR_STID_MASK;
+ regval |= (uint32_t)msg->cm_hdr.ch_id << CAN_TIR_STID_SHIFT;
+#endif
+ can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval);
+
+ /* Set up the DLC */
+
+ dlc = msg->cm_hdr.ch_dlc;
+ regval = can_getreg(priv, STM32_CAN_TDTR_OFFSET(txmb));
+ regval &= ~(CAN_TDTR_DLC_MASK | CAN_TDTR_TGT);
+ regval |= (uint32_t)dlc << CAN_TDTR_DLC_SHIFT;
+ can_putreg(priv, STM32_CAN_TDTR_OFFSET(txmb), regval);
+
+ /* Set up the data fields */
+
+ ptr = msg->cm_data;
+ regval = 0;
+
+ if (dlc > 0)
+ {
+ tmp = (uint32_t)*ptr++;
+ regval = tmp << CAN_TDLR_DATA0_SHIFT;
+
+ if (dlc > 1)
+ {
+ tmp = (uint32_t)*ptr++;
+ regval |= tmp << CAN_TDLR_DATA1_SHIFT;
+
+ if (dlc > 2)
+ {
+ tmp = (uint32_t)*ptr++;
+ regval |= tmp << CAN_TDLR_DATA2_SHIFT;
+
+ if (dlc > 3)
+ {
+ tmp = (uint32_t)*ptr++;
+ regval |= tmp << CAN_TDLR_DATA3_SHIFT;
+ }
+ }
+ }
+ }
+ can_putreg(priv, STM32_CAN_TDLR_OFFSET(txmb), regval);
+
+ regval = 0;
+ if (dlc > 4)
+ {
+ tmp = (uint32_t)*ptr++;
+ regval = tmp << CAN_TDHR_DATA4_SHIFT;
+
+ if (dlc > 5)
+ {
+ tmp = (uint32_t)*ptr++;
+ regval |= tmp << CAN_TDHR_DATA5_SHIFT;
+
+ if (dlc > 6)
+ {
+ tmp = (uint32_t)*ptr++;
+ regval |= tmp << CAN_TDHR_DATA6_SHIFT;
+
+ if (dlc > 7)
+ {
+ tmp = (uint32_t)*ptr++;
+ regval |= tmp << CAN_TDHR_DATA7_SHIFT;
+ }
+ }
+ }
+ }
+ can_putreg(priv, STM32_CAN_TDHR_OFFSET(txmb), regval);
+
+ /* Enable the transmit mailbox empty interrupt (may already be enabled) */
+
+ regval = can_getreg(priv, STM32_CAN_IER_OFFSET);
+ regval |= CAN_IER_TMEIE;
+ can_putreg(priv, STM32_CAN_IER_OFFSET, regval);
+
+ /* Request transmission */
+
+ regval = can_getreg(priv, STM32_CAN_TIR_OFFSET(txmb));
+ regval |= CAN_TIR_TXRQ; /* Transmit Mailbox Request */
+ can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval);
+
+ can_dumpmbregs(priv, "After send");
+ return OK;
+}
+
+/****************************************************************************
+ * Name: can_txready
+ *
+ * Description:
+ * Return true if the CAN hardware can accept another TX message.
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * True if the CAN hardware is ready to accept another TX message.
+ *
+ ****************************************************************************/
+
+static bool can_txready(FAR struct can_dev_s *dev)
+{
+ FAR struct stm32_can_s *priv = dev->cd_priv;
+ uint32_t regval;
+
+ /* Return true if any mailbox is available */
+
+ regval = can_getreg(priv, STM32_CAN_TSR_OFFSET);
+ canllvdbg("CAN%d TSR: %08x\n", priv->port, regval);
+
+ if ((regval & CAN_ALL_MAILBOXES) != 0)
+ {
+ return true;
+ }
+ return false;
+}
+
+/****************************************************************************
+ * Name: can_txempty
+ *
+ * Description:
+ * Return true if all message have been sent. If for example, the CAN
+ * hardware implements FIFOs, then this would mean the transmit FIFO is
+ * empty. This method is called when the driver needs to make sure that
+ * all characters are "drained" from the TX hardware before calling
+ * co_shutdown().
+ *
+ * Input Parameters:
+ * dev - An instance of the "upper half" can driver state structure.
+ *
+ * Returned Value:
+ * True if there are no pending TX transfers in the CAN hardware.
+ *
+ ****************************************************************************/
+
+static bool can_txempty(FAR struct can_dev_s *dev)
+{
+ FAR struct stm32_can_s *priv = dev->cd_priv;
+ uint32_t regval;
+
+ /* Return true if all mailboxes are available */
+
+ regval = can_getreg(priv, STM32_CAN_TSR_OFFSET);
+ canllvdbg("CAN%d TSR: %08x\n", priv->port, regval);
+
+ if ((regval & CAN_ALL_MAILBOXES) == CAN_ALL_MAILBOXES)
+ {
+ return true;
+ }
+ return false;
+}
+
+/****************************************************************************
+ * Name: can_rx0interrupt
+ *
+ * Description:
+ * CAN RX FIFO 0 interrupt handler
+ *
+ * Input Parameters:
+ * irq - The IRQ number of the interrupt.
+ * context - The register state save array at the time of the interrupt.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int can_rx0interrupt(int irq, void *context)
+{
+ FAR struct can_dev_s *dev = NULL;
+ FAR struct stm32_can_s *priv;
+ struct can_hdr_s hdr;
+ uint8_t data[CAN_MAXDATALEN];
+ uint32_t regval;
+ int npending;
+ int ret;
+
+#if defined(CONFIG_STM32_CAN1) && defined(CONFIG_STM32_CAN2)
+ if (g_can1priv.canrx0 == irq)
+ {
+ dev = &g_can1dev;
+ }
+ else if (g_can2priv.canrx0 == irq)
+ {
+ dev = &g_can2dev;
+ }
+ else
+ {
+ PANIC(OSERR_UNEXPECTEDISR);
+ }
+#elif defined(CONFIG_STM32_CAN1)
+ dev = &g_can1dev;
+#else /* defined(CONFIG_STM32_CAN2) */
+ dev = &g_can2dev;
+#endif
+ priv = dev->cd_priv;
+
+ /* Verify that a message is pending in FIFO 0 */
+
+ regval = can_getreg(priv, STM32_CAN_RF0R_OFFSET);
+ npending = (regval & CAN_RFR_FMP_MASK) >> CAN_RFR_FMP_SHIFT;
+ if (npending < 1)
+ {
+ canlldbg("WARNING: No messages pending\n");
+ return OK;
+ }
+
+ can_dumpmbregs(priv, "RX0 interrupt");
+
+ /* Get the CAN identifier. */
+
+ regval = can_getreg(priv, STM32_CAN_RI0R_OFFSET);
+#ifdef CONFIG_CAN_EXTID
+ if ((regval & CAN_RIR_IDE) != 0)
+ {
+ hdr.ch_id = (regval & CAN_RIR_EXID_MASK) >> CAN_RIR_EXID_SHIFT;
+ hdr.ch_extid = true;
+ }
+ else
+ {
+ hdr.ch_id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT;
+ hdr.ch_extid = false;
+ }
+#else
+ if ((regval & CAN_RIR_IDE) != 0)
+ {
+ canlldbg("ERROR: Received message with extended identifier. Dropped\n");
+ ret = -ENOSYS;
+ goto errout;
+ }
+
+ hdr.ch_id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT;
+#endif
+
+ /* Extract the RTR bit */
+
+ hdr.ch_rtr = (regval & CAN_RIR_RTR) != 0 ? true : false;
+
+ /* Get the DLC */
+
+ regval = can_getreg(priv, STM32_CAN_RDT0R_OFFSET);
+ hdr.ch_dlc = (regval & CAN_RDTR_DLC_MASK) >> CAN_RDTR_DLC_SHIFT;
+
+ /* Save the message data */
+
+ regval = can_getreg(priv, STM32_CAN_RDL0R_OFFSET);
+ data[0] = (regval & CAN_RDLR_DATA0_MASK) >> CAN_RDLR_DATA0_SHIFT;
+ data[1] = (regval & CAN_RDLR_DATA1_MASK) >> CAN_RDLR_DATA1_SHIFT;
+ data[2] = (regval & CAN_RDLR_DATA2_MASK) >> CAN_RDLR_DATA2_SHIFT;
+ data[3] = (regval & CAN_RDLR_DATA3_MASK) >> CAN_RDLR_DATA3_SHIFT;
+
+ regval = can_getreg(priv, STM32_CAN_RDH0R_OFFSET);
+ data[4] = (regval & CAN_RDHR_DATA4_MASK) >> CAN_RDHR_DATA4_SHIFT;
+ data[5] = (regval & CAN_RDHR_DATA5_MASK) >> CAN_RDHR_DATA5_SHIFT;
+ data[6] = (regval & CAN_RDHR_DATA6_MASK) >> CAN_RDHR_DATA6_SHIFT;
+ data[7] = (regval & CAN_RDHR_DATA7_MASK) >> CAN_RDHR_DATA7_SHIFT;
+
+ /* Provide the data to the upper half driver */
+
+ ret = can_receive(dev, &hdr, data);
+
+ /* Release the FIFO0 */
+
+#ifndef CONFIG_CAN_EXTID
+errout:
+#endif
+ regval = can_getreg(priv, STM32_CAN_RF0R_OFFSET);
+ regval |= CAN_RFR_RFOM;
+ can_putreg(priv, STM32_CAN_RF0R_OFFSET, regval);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: can_txinterrupt
+ *
+ * Description:
+ * CAN TX mailbox complete interrupt handler
+ *
+ * Input Parameters:
+ * irq - The IRQ number of the interrupt.
+ * context - The register state save array at the time of the interrupt.
+ *
+ * Returned Value:
+ * Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int can_txinterrupt(int irq, void *context)
+{
+ FAR struct can_dev_s *dev = NULL;
+ FAR struct stm32_can_s *priv;
+ uint32_t regval;
+
+#if defined(CONFIG_STM32_CAN1) && defined(CONFIG_STM32_CAN2)
+ if (g_can1priv.cantx == irq)
+ {
+ dev = &g_can1dev;
+ }
+ else if (g_can2priv.cantx == irq)
+ {
+ dev = &g_can2dev;
+ }
+ else
+ {
+ PANIC(OSERR_UNEXPECTEDISR);
+ }
+#elif defined(CONFIG_STM32_CAN1)
+ dev = &g_can1dev;
+#else /* defined(CONFIG_STM32_CAN2) */
+ dev = &g_can2dev;
+#endif
+ priv = dev->cd_priv;
+
+ /* Get the transmit status */
+
+ regval = can_getreg(priv, STM32_CAN_TSR_OFFSET);
+
+ /* Check for RQCP0: Request completed mailbox 0 */
+
+ if ((regval & CAN_TSR_RQCP0) != 0)
+ {
+ /* Writing '1' to RCP0 clears RCP0 and all the status bits (TXOK0,
+ * ALST0 and TERR0) for Mailbox 0.
+ */
+
+ can_putreg(priv, STM32_CAN_TSR_OFFSET, CAN_TSR_RQCP0);
+
+ /* Check for errors */
+
+ if ((regval & CAN_TSR_TXOK0) != 0)
+ {
+ /* Tell the upper half that the tansfer is finished. */
+
+ (void)can_txdone(dev);
+ }
+ }
+
+ /* Check for RQCP1: Request completed mailbox 1 */
+
+ if ((regval & CAN_TSR_RQCP1) != 0)
+ {
+ /* Writing '1' to RCP1 clears RCP1 and all the status bits (TXOK1,
+ * ALST1 and TERR1) for Mailbox 1.
+ */
+
+ can_putreg(priv, STM32_CAN_TSR_OFFSET, CAN_TSR_RQCP1);
+
+ /* Check for errors */
+
+ if ((regval & CAN_TSR_TXOK1) != 0)
+ {
+ /* Tell the upper half that the tansfer is finished. */
+
+ (void)can_txdone(dev);
+ }
+ }
+
+ /* Check for RQCP2: Request completed mailbox 2 */
+
+ if ((regval & CAN_TSR_RQCP2) != 0)
+ {
+ /* Writing '1' to RCP2 clears RCP2 and all the status bits (TXOK2,
+ * ALST2 and TERR2) for Mailbox 2.
+ */
+
+ can_putreg(priv, STM32_CAN_TSR_OFFSET, CAN_TSR_RQCP2);
+
+ /* Check for errors */
+
+ if ((regval & CAN_TSR_TXOK2) != 0)
+ {
+ /* Tell the upper half that the tansfer is finished. */
+
+ (void)can_txdone(dev);
+ }
+ }
+
+ /* Were all transmissions complete in all mailboxes when we entered this
+ * handler?
+ */
+
+ if ((regval & CAN_ALL_MAILBOXES) == CAN_ALL_MAILBOXES)
+ {
+ /* Yes.. disable further TX interrupts */
+
+ regval = can_getreg(priv, STM32_CAN_IER_OFFSET);
+ regval &= ~CAN_IER_TMEIE;
+ can_putreg(priv, STM32_CAN_IER_OFFSET, regval);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: can_bittiming
+ *
+ * Description:
+ * Set the CAN bit timing register (BTR) based on the configured BAUD.
+ *
+ * "The bit timing logic monitors the serial bus-line and performs sampling
+ * and adjustment of the sample point by synchronizing on the start-bit edge
+ * and resynchronizing on the following edges.
+ *
+ * "Its operation may be explained simply by splitting nominal bit time into
+ * three segments as follows:
+ *
+ * 1. "Synchronization segment (SYNC_SEG): a bit change is expected to occur
+ * within this time segment. It has a fixed length of one time quantum
+ * (1 x tCAN).
+ * 2. "Bit segment 1 (BS1): defines the location of the sample point. It
+ * includes the PROP_SEG and PHASE_SEG1 of the CAN standard. Its duration
+ * is programmable between 1 and 16 time quanta but may be automatically
+ * lengthened to compensate for positive phase drifts due to differences
+ * in the frequency of the various nodes of the network.
+ * 3. "Bit segment 2 (BS2): defines the location of the transmit point. It
+ * represents the PHASE_SEG2 of the CAN standard. Its duration is
+ * programmable between 1 and 8 time quanta but may also be automatically
+ * shortened to compensate for negative phase drifts."
+ *
+ * Pictorially:
+ *
+ * |<----------------- NOMINAL BIT TIME ----------------->|
+ * |<- SYNC_SEG ->|<------ BS1 ------>|<------ BS2 ------>|
+ * |<---- Tq ---->|<----- Tbs1 ------>|<----- Tbs2 ------>|
+ *
+ * Where
+ * Tbs1 is the duration of the BS1 segment
+ * Tbs2 is the duration of the BS2 segment
+ * Tq is the "Time Quantum"
+ *
+ * Relationships:
+ *
+ * baud = 1 / bit_time
+ * bit_time = Tq + Tbs1 + Tbs2
+ * Tbs1 = Tq * ts1
+ * Tbs2 = Tq * ts2
+ * Tq = brp * Tpclk1
+ *
+ * Where:
+ * Tpclk1 is the period of the APB1 clock (PCLK1).
+ *
+ * Input Parameter:
+ * priv - A reference to the CAN block status
+ *
+ * Returned Value:
+ * Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int can_bittiming(struct stm32_can_s *priv)
+{
+ uint32_t tmp;
+ uint32_t brp;
+ uint32_t ts1;
+ uint32_t ts2;
+
+ canllvdbg("CAN%d PCLK1: %d baud: %d\n",
+ priv->port, STM32_PCLK1_FREQUENCY, priv->baud);
+
+ /* Try to get CAN_BIT_QUANTA quanta in one bit_time.
+ *
+ * bit_time = Tq*(ts1 + ts2 + 1)
+ * nquanta = bit_time / Tq
+ * nquanta = (ts1 + ts2 + 1)
+ *
+ * bit_time = brp * Tpclk1 * (ts1 + ts2 + 1)
+ * nquanta = bit_time / brp / Tpclk1
+ * = PCLK1 / baud / brp
+ * brp = PCLK1 / baud / nquanta;
+ *
+ * Example:
+ * PCLK1 = 42,000,000 baud = 1,000,000 nquanta = 14 : brp = 3
+ * PCLK1 = 42,000,000 baud = 700,000 nquanta = 14 : brp = 4
+ */
+
+ tmp = STM32_PCLK1_FREQUENCY / priv->baud;
+ if (tmp < CAN_BIT_QUANTA)
+ {
+ /* At the smallest brp value (1), there are already too few bit times
+ * (PCLCK1 / baud) to meet our goal. brp must be one and we need
+ * make some reasonable guesses about ts1 and ts2.
+ */
+
+ brp = 1;
+
+ /* In this case, we have to guess a good value for ts1 and ts2 */
+
+ ts1 = (tmp - 1) >> 1;
+ ts2 = tmp - ts1 - 1;
+ if (ts1 == ts2 && ts1 > 1 && ts2 < CAN_BTR_TSEG2_MAX)
+ {
+ ts1--;
+ ts2++;
+ }
+ }
+
+ /* Otherwise, nquanta is CAN_BIT_QUANTA, ts1 is CONFIG_CAN_TSEG1, ts2 is
+ * CONFIG_CAN_TSEG2 and we calculate brp to achieve CAN_BIT_QUANTA quanta
+ * in the bit time
+ */
+
+ else
+ {
+ ts1 = CONFIG_CAN_TSEG1;
+ ts2 = CONFIG_CAN_TSEG2;
+ brp = (tmp + (CAN_BIT_QUANTA/2)) / CAN_BIT_QUANTA;
+ DEBUGASSERT(brp >=1 && brp <= CAN_BTR_BRP_MAX);
+ }
+
+ canllvdbg("TS1: %d TS2: %d BRP: %d\n", ts1, ts2, brp);
+
+ /* Configure bit timing. This also does the the following, less obvious
+ * things. Unless loopback mode is enabled, it:
+ *
+ * - Disables silent mode.
+ * - Disables loopback mode.
+ *
+ * NOTE that for the time being, SJW is set to 1 just because I don't
+ * know any better.
+ */
+
+ tmp = ((brp - 1) << CAN_BTR_BRP_SHIFT) | ((ts1 - 1) << CAN_BTR_TS1_SHIFT) |
+ ((ts2 - 1) << CAN_BTR_TS2_SHIFT) | ((1 - 1) << CAN_BTR_SJW_SHIFT);
+#ifdef CONFIG_CAN_LOOPBACK
+//tmp |= (CAN_BTR_LBKM | CAN_BTR_SILM);
+ tmp |= CAN_BTR_LBKM;
+#endif
+
+ can_putreg(priv, STM32_CAN_BTR_OFFSET, tmp);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: can_cellinit
+ *
+ * Description:
+ * CAN cell initialization
+ *
+ * Input Parameter:
+ * priv - A pointer to the private data structure for this CAN block
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int can_cellinit(struct stm32_can_s *priv)
+{
+ volatile uint32_t timeout;
+ uint32_t regval;
+ int ret;
+
+ canllvdbg("CAN%d\n", priv->port);
+
+ /* Exit from sleep mode */
+
+ regval = can_getreg(priv, STM32_CAN_MCR_OFFSET);
+ regval &= ~CAN_MCR_SLEEP;
+ can_putreg(priv, STM32_CAN_MCR_OFFSET, regval);
+
+ /* Configure CAN behavior. Priority driven request order, not message ID. */
+
+ regval |= CAN_MCR_TXFP;
+ can_putreg(priv, STM32_CAN_MCR_OFFSET, regval);
+
+ /* Enter initialization mode */
+
+ regval |= CAN_MCR_INRQ;
+ can_putreg(priv, STM32_CAN_MCR_OFFSET, regval);
+
+ /* Wait until initialization mode is acknowledged */
+
+ for (timeout = INAK_TIMEOUT; timeout > 0; timeout--)
+ {
+ regval = can_getreg(priv, STM32_CAN_MSR_OFFSET);
+ if ((regval & CAN_MSR_INAK) != 0)
+ {
+ /* We are in initialization mode */
+
+ break;
+ }
+ }
+
+ /* Check for a timeout */
+
+ if (timeout < 1)
+ {
+ canlldbg("ERROR: Timed out waiting to enter initialization mode\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Disable the following modes:
+ *
+ * - Time triggered communication mode
+ * - Automatic bus-off management
+ * - Automatic wake-up mode
+ * - No automatic retransmission
+ * - Receive FIFO locked mode
+ * - Transmit FIFO priority
+ */
+
+ regval = can_getreg(priv, STM32_CAN_MCR_OFFSET);
+ regval &= ~(CAN_MCR_TXFP | CAN_MCR_RFLM | CAN_MCR_NART | CAN_MCR_AWUM | CAN_MCR_ABOM | CAN_MCR_TTCM);
+ can_putreg(priv, STM32_CAN_MCR_OFFSET, regval);
+
+ /* Configure bit timing. */
+
+ ret = can_bittiming(priv);
+ if (ret < 0)
+ {
+ canlldbg("ERROR: Failed to set bit timing: %d\n", ret);
+ return ret;
+ }
+
+ /* Exit initialization mode */
+
+ regval = can_getreg(priv, STM32_CAN_MCR_OFFSET);
+ regval &= ~CAN_MCR_INRQ;
+ can_putreg(priv, STM32_CAN_MCR_OFFSET, regval);
+
+ /* Wait until the initialization mode exit is acknowledged */
+
+ for (timeout = INAK_TIMEOUT; timeout > 0; timeout--)
+ {
+ regval = can_getreg(priv, STM32_CAN_MSR_OFFSET);
+ if ((regval & CAN_MSR_INAK) == 0)
+ {
+ /* We are out of initialization mode */
+
+ break;
+ }
+ }
+
+ /* Check for a timeout */
+
+ if (timeout < 1)
+ {
+ canlldbg("ERROR: Timed out waiting to exit initialization mode: %08x\n", regval);
+ return -ETIMEDOUT;
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Name: can_filterinit
+ *
+ * Description:
+ * CAN filter initialization. CAN filters are not currently used by this
+ * driver. The CAN filters can be configured in a different way:
+ *
+ * 1. As a match of specific IDs in a list (IdList mode), or as
+ * 2. And ID and a mask (IdMask mode).
+ *
+ * Filters can also be configured as:
+ *
+ * 3. 16- or 32-bit. The advantage of 16-bit filters is that you get
+ * more filters; The advantage of 32-bit filters is that you get
+ * finer control of the filtering.
+ *
+ * One filter is set up for each CAN. The filter resources are shared
+ * between the two CAN modules: CAN1 uses only filter 0 (but reserves
+ * 0 through CAN_NFILTERS/2-1); CAN2 uses only filter CAN_NFILTERS/2
+ * (but reserves CAN_NFILTERS/2 through CAN_NFILTERS-1).
+ *
+ * 32-bit IdMask mode is configured. However, both the ID and the MASK
+ * are set to zero thus supressing all filtering because anything masked
+ * with zero matches zero.
+ *
+ * Input Parameter:
+ * priv - A pointer to the private data structure for this CAN block
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int can_filterinit(struct stm32_can_s *priv)
+{
+ uint32_t regval;
+ uint32_t bitmask;
+
+ canllvdbg("CAN%d filter: %d\n", priv->port, priv->filter);
+
+ /* Get the bitmask associated with the filter used by this CAN block */
+
+ bitmask = ((uint32_t)1) << priv->filter;
+
+ /* Enter filter initialization mode */
+
+ regval = can_getreg(priv, STM32_CAN_FMR_OFFSET);
+ regval |= CAN_FMR_FINIT;
+ can_putreg(priv, STM32_CAN_FMR_OFFSET, regval);
+
+ /* Disable the filter */
+
+ regval = can_getreg(priv, STM32_CAN_FA1R_OFFSET);
+ regval &= ~bitmask;
+ can_putreg(priv, STM32_CAN_FA1R_OFFSET, regval);
+
+ /* Select the 32-bit scale for the filter */
+
+ regval = can_getreg(priv, STM32_CAN_FS1R_OFFSET);
+ regval |= bitmask;
+ can_putreg(priv, STM32_CAN_FS1R_OFFSET, regval);
+
+ /* There are 14 or 28 filter banks (depending) on the device. Each filter bank is
+ * composed of two 32-bit registers, CAN_FiR:
+ */
+
+ can_putreg(priv, STM32_CAN_FR_OFFSET(priv->filter, 1), 0);
+ can_putreg(priv, STM32_CAN_FR_OFFSET(priv->filter, 2), 0);
+
+ /* Set Id/Mask mode for the filter */
+
+ regval = can_getreg(priv, STM32_CAN_FM1R_OFFSET);
+ regval &= ~bitmask;
+ can_putreg(priv, STM32_CAN_FM1R_OFFSET, regval);
+
+ /* Assign FIFO 0 for the filter */
+
+ regval = can_getreg(priv, STM32_CAN_FFA1R_OFFSET);
+ regval &= ~bitmask;
+ can_putreg(priv, STM32_CAN_FFA1R_OFFSET, regval);
+
+ /* Enable the filter */
+
+ regval = can_getreg(priv, STM32_CAN_FA1R_OFFSET);
+ regval |= bitmask;
+ can_putreg(priv, STM32_CAN_FA1R_OFFSET, regval);
+
+ /* Exit filter initialization mode */
+
+ regval = can_getreg(priv, STM32_CAN_FMR_OFFSET);
+ regval &= ~CAN_FMR_FINIT;
+ can_putreg(priv, STM32_CAN_FMR_OFFSET, regval);
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_caninitialize
+ *
+ * Description:
+ * Initialize the selected CAN port
+ *
+ * Input Parameter:
+ * Port number (for hardware that has mutiple CAN interfaces)
+ *
+ * Returned Value:
+ * Valid CAN device structure reference on succcess; a NULL on failure
+ *
+ ****************************************************************************/
+
+FAR struct can_dev_s *stm32_caninitialize(int port)
+{
+ struct can_dev_s *dev = NULL;
+
+ canvdbg("CAN%d\n", port);
+
+ /* NOTE: Peripherical clocking for CAN1 and/or CAN2 was already provided
+ * by stm32_clockconfig() early in the reset sequence.
+ */
+
+#ifdef CONFIG_STM32_CAN1
+ if( port == 1 )
+ {
+ /* Select the CAN1 device structure */
+
+ dev = &g_can1dev;
+
+ /* Configure CAN1 pins. The ambiguous settings in the stm32*_pinmap.h
+ * file must have been disambiguated in the board.h file.
+ */
+
+ stm32_configgpio(GPIO_CAN1_RX);
+ stm32_configgpio(GPIO_CAN1_TX);
+ }
+ else
+#endif
+#ifdef CONFIG_STM32_CAN2
+ if ( port ==2 )
+ {
+ /* Select the CAN2 device structure */
+
+ dev = &g_can2dev;
+
+ /* Configure CAN2 pins. The ambiguous settings in the stm32*_pinmap.h
+ * file must have been disambiguated in the board.h file.
+ */
+
+ stm32_configgpio(GPIO_CAN2_RX);
+ stm32_configgpio(GPIO_CAN2_TX);
+ }
+ else
+#endif
+ {
+ candbg("ERROR: Unsupported port %d\n", port);
+ return NULL;
+ }
+
+ return dev;
+}
+
+#endif /* CONFIG_CAN && (CONFIG_STM32_CAN1 || CONFIG_STM32_CAN2) */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_can.h b/nuttx/arch/arm/src/stm32/stm32_can.h
new file mode 100644
index 000000000..15203b5c9
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_can.h
@@ -0,0 +1,145 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_can.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_STM32_CAN_H
+#define __ARCH_ARM_SRC_STM32_STM32_CAN_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_can.h"
+
+#include <nuttx/can.h>
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* Up to 2 CAN interfaces are supported */
+
+#if STM32_NCAN < 2
+# undef CONFIG_STM32_CAN2
+#endif
+
+#if STM32_NCAN < 1
+# undef CONFIG_STM32_CAN1
+#endif
+
+#if defined(CONFIG_CAN) && (defined(CONFIG_STM32_CAN1) || defined(CONFIG_STM32_CAN2))
+
+/* CAN BAUD */
+
+#if defined(CONFIG_STM32_CAN1) && !defined(CONFIG_CAN1_BAUD)
+# error "CONFIG_CAN1_BAUD is not defined"
+#endif
+
+#if defined(CONFIG_STM32_CAN2) && !defined(CONFIG_CAN2_BAUD)
+# error "CONFIG_CAN2_BAUD is not defined"
+#endif
+
+/* User-defined TSEG1 and TSEG2 settings may be used.
+ *
+ * CONFIG_CAN_TSEG1 = the number of CAN time quanta in segment 1
+ * CONFIG_CAN_TSEG2 = the number of CAN time quanta in segment 2
+ * CAN_BIT_QUANTA = The number of CAN time quanta in on bit time
+ */
+
+#ifndef CONFIG_CAN_TSEG1
+# define CONFIG_CAN_TSEG1 6
+#endif
+
+#if CONFIG_CAN_TSEG1 < 1 || CONFIG_CAN_TSEG1 > CAN_BTR_TSEG1_MAX
+# errror "CONFIG_CAN_TSEG1 is out of range"
+#endif
+
+#ifndef CONFIG_CAN_TSEG2
+# define CONFIG_CAN_TSEG2 7
+#endif
+
+#if CONFIG_CAN_TSEG2 < 1 || CONFIG_CAN_TSEG2 > CAN_BTR_TSEG2_MAX
+# errror "CONFIG_CAN_TSEG2 is out of range"
+#endif
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_caninitialize
+ *
+ * Description:
+ * Initialize the selected CAN port
+ *
+ * Input Parameter:
+ * Port number (for hardware that has mutiple CAN interfaces)
+ *
+ * Returned Value:
+ * Valid CAN device structure reference on succcess; a NULL on failure
+ *
+ ****************************************************************************/
+
+struct can_dev_s;
+EXTERN FAR struct can_dev_s *stm32_caninitialize(int port);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_CAN && (CONFIG_STM32_CAN1 || CONFIG_STM32_CAN2) */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_CAN_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_dac.c b/nuttx/arch/arm/src/stm32/stm32_dac.c
new file mode 100644
index 000000000..b92da7b71
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_dac.c
@@ -0,0 +1,860 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_dac.c
+ *
+ * Copyright (C) 2011 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 <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+#include <nuttx/arch.h>
+#include <nuttx/analog/dac.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "chip.h"
+#include "stm32_internal.h"
+#include "stm32_dac.h"
+
+#ifdef CONFIG_DAC
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+/* Up to 2 DAC interfaces are supported */
+
+#if STM32_NDAC < 2
+# undef CONFIG_STM32_DAC2
+# undef CONFIG_STM32_DAC2_DMA
+# undef CONFIG_STM32_DAC2_TIMER
+# undef CONFIG_STM32_DAC2_TIMER_FREQUENCY
+#endif
+
+#if STM32_NDAC < 1
+# undef CONFIG_STM32_DAC1
+# undef CONFIG_STM32_DAC1_DMA
+# undef CONFIG_STM32_DAC1_TIMER
+# undef CONFIG_STM32_DAC1_TIMER_FREQUENCY
+#endif
+
+#if defined(CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2)
+
+/* DMA configuration. */
+
+#if defined(CONFIG_STM32_DAC1_DMA) || defined(CONFIG_STM32_DAC2_DMA)
+# if defined(CONFIG_STM32_STM32F10XX)
+# ifndef CONFIG_STM32_DMA2
+# warning "STM32 F1 DAC DMA support requires CONFIG_STM32_DMA2"
+# undef CONFIG_STM32_DAC1_DMA
+# undef CONFIG_STM32_DAC2_DMA
+# endif
+# elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# ifndef CONFIG_STM32_DMA1
+# warning "STM32 F4 DAC DMA support requires CONFIG_STM32_DMA1"
+# undef CONFIG_STM32_DAC1_DMA
+# undef CONFIG_STM32_DAC2_DMA
+# endif
+# else
+# warning "No DAC DMA information for this STM32 family"
+# undef CONFIG_STM32_DAC1_DMA
+# undef CONFIG_STM32_DAC2_DMA
+# endif
+#endif
+
+/* If DMA is selected, then a timer and output frequency must also be
+ * provided to support the DMA transfer. The DMA transfer could be
+ * supported by and EXTI trigger, but this feature is not currently
+ * supported by the driver.
+ */
+
+#ifdef CONFIG_STM32_DAC1_DMA
+# if !defined(CONFIG_STM32_DAC1_TIMER)
+# warning "A timer number must be specificed in CONFIG_STM32_DAC1_TIMER"
+# undef CONFIG_STM32_DAC1_DMA
+# undef CONFIG_STM32_DAC1_TIMER_FREQUENCY
+# elif !defined(CONFIG_STM32_DAC1_TIMER_FREQUENCY)
+# warning "A timer frequency must be specificed in CONFIG_STM32_DAC1_TIMER_FREQUENCY"
+# undef CONFIG_STM32_DAC1_DMA
+# undef CONFIG_STM32_DAC1_TIMER
+# endif
+#endif
+
+#ifdef CONFIG_STM32_DAC2_DMA
+# if !defined(CONFIG_STM32_DAC2_TIMER)
+# warning "A timer number must be specificed in CONFIG_STM32_DAC2_TIMER"
+# undef CONFIG_STM32_DAC2_DMA
+# undef CONFIG_STM32_DAC2_TIMER_FREQUENCY
+# elif !defined(CONFIG_STM32_DAC2_TIMER_FREQUENCY)
+# warning "A timer frequency must be specificed in CONFIG_STM32_DAC2_TIMER_FREQUENCY"
+# undef CONFIG_STM32_DAC2_DMA
+# undef CONFIG_STM32_DAC2_TIMER
+# endif
+#endif
+
+/* DMA *********************************************************************/
+/* DMA channels and interface values differ for the F1 and F4 families */
+
+#undef HAVE_DMA
+#if defined(CONFIG_STM32_DAC1_DMA) || defined(CONFIG_STM32_DAC2_DMA)
+# if defined(CONFIG_STM32_STM32F10XX)
+# define HAVE_DMA 1
+# define DAC_DMA 2
+# define DAC1_DMA_CHAN DMACHAN_DAC_CHAN1
+# define DAC2_DMA_CHAN DMACHAN_DAC_CHAN2
+# elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define HAVE_DMA 1
+# define DAC_DMA 1
+# define DAC1_DMA_CHAN DMAMAP_DAC1
+# define DAC2_DMA_CHAN DMAMAP_DAC2
+# endif
+#endif
+
+/* Timer configuration. The STM32 supports 8 different trigger for DAC
+ * output:
+ *
+ * TSEL SOURCE DEVICES
+ * ---- ----------------------- -------------------------------------
+ * 000 Timer 6 TRGO event ALL
+ * 001 Timer 3 TRGO event STM32 F1 Connectivity Line
+ * Timer 8 TRGO event Other STM32 F1 and all STM32 F4
+ * 010 Timer 7 TRGO event ALL
+ * 011 Timer 5 TRGO event ALL
+ * 100 Timer 2 TRGO event ALL
+ * 101 Timer 4 TRGO event ALL
+ * 110 EXTI line9 ALL
+ * 111 SWTRIG Software control ALL
+ *
+ * This driver does not support the EXTI trigger.
+ */
+
+#ifdef CONFIG_STM32_DAC1_DMA
+# if CONFIG_STM32_DAC1_TIMER == 6
+# ifndef CONFIG_STM32_TIM6_DAC
+# error "CONFIG_STM32_TIM6_DAC required for DAC1"
+# endif
+# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM6
+# define DAC1_TIMER_BASE STM32_TIM6_BASE
+# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# elif CONFIG_STM32_DAC1_TIMER == 3 && defined(CONFIG_STM32_CONNECTIVITYLINE)
+# ifndef CONFIG_STM32_TIM3_DAC
+# error "CONFIG_STM32_TIM3_DAC required for DAC1"
+# endif
+# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM3
+# define DAC1_TIMER_BASE STM32_TIM3_BASE
+# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# elif CONFIG_STM32_DAC1_TIMER == 8 && !defined(CONFIG_STM32_CONNECTIVITYLINE)
+# ifndef CONFIG_STM32_TIM8_DAC
+# error "CONFIG_STM32_TIM8_DAC required for DAC1"
+# endif
+# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM8
+# define DAC1_TIMER_BASE STM32_TIM8_BASE
+# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
+# elif CONFIG_STM32_DAC1_TIMER == 7
+# ifndef CONFIG_STM32_TIM7_DAC
+# error "CONFIG_STM32_TIM7_DAC required for DAC1"
+# endif
+# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM7
+# define DAC1_TIMER_BASE STM32_TIM7_BASE
+# elif CONFIG_STM32_DAC1_TIMER == 5
+# ifndef CONFIG_STM32_TIM5_DAC
+# error "CONFIG_STM32_TIM5_DAC required for DAC1"
+# endif
+# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM5
+# define DAC1_TIMER_BASE STM32_TIM5_BASE
+# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# elif CONFIG_STM32_DAC1_TIMER == 2
+# ifndef CONFIG_STM32_TIM2_DAC
+# error "CONFIG_STM32_TIM2_DAC required for DAC1"
+# endif
+# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM2
+# define DAC1_TIMER_BASE STM32_TIM2_BASE
+# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# elif CONFIG_STM32_DAC1_TIMER == 4
+# ifndef CONFIG_STM32_TIM4_DAC
+# error "CONFIG_STM32_TIM4_DAC required for DAC1"
+# endif
+# define DAC1_TSEL_VALUE DAC_CR_TSEL_TIM4
+# define DAC1_TIMER_BASE STM32_TIM4_BASE
+# define DAC1_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# else
+# error "Unsupported CONFIG_STM32_DAC1_TIMER"
+# endif
+#else
+# define DAC1_TSEL_VALUE DAC_CR_TSEL_SW
+#endif
+
+#ifdef CONFIG_STM32_DAC2_DMA
+# if CONFIG_STM32_DAC2_TIMER == 6
+# ifndef CONFIG_STM32_TIM6_DAC
+# error "CONFIG_STM32_TIM6_DAC required for DAC2"
+# endif
+# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM6
+# define DAC2_TIMER_BASE STM32_TIM6_BASE
+# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# elif CONFIG_STM32_DAC2_TIMER == 3 && defined(CONFIG_STM32_CONNECTIVITYLINE)
+# ifndef CONFIG_STM32_TIM3_DAC
+# error "CONFIG_STM32_TIM3_DAC required for DAC2"
+# endif
+# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM3
+# define DAC2_TIMER_BASE STM32_TIM3_BASE
+# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# elif CONFIG_STM32_DAC2_TIMER == 8 && !defined(CONFIG_STM32_CONNECTIVITYLINE)
+# ifndef CONFIG_STM32_TIM8_DAC
+# error "CONFIG_STM32_TIM8_DAC required for DAC2"
+# endif
+# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM8
+# define DAC2_TIMER_BASE STM32_TIM8_BASE
+# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK2_FREQUENCY
+# elif CONFIG_STM32_DAC2_TIMER == 7
+# ifndef CONFIG_STM32_TIM7_DAC
+# error "CONFIG_STM32_TIM7_DAC required for DAC2"
+# endif
+# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM7
+# define DAC2_TIMER_BASE STM32_TIM7_BASE
+# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# elif CONFIG_STM32_DAC2_TIMER == 5
+# ifndef CONFIG_STM32_TIM5_DAC
+# error "CONFIG_STM32_TIM5_DAC required for DAC2"
+# endif
+# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM5
+# define DAC2_TIMER_BASE STM32_TIM5_BASE
+# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# elif CONFIG_STM32_DAC2_TIMER == 2
+# ifndef CONFIG_STM32_TIM2_DAC
+# error "CONFIG_STM32_TIM2_DAC required for DAC2"
+# endif
+# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM2
+# define DAC2_TIMER_BASE STM32_TIM2_BASE
+# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# elif CONFIG_STM32_DAC2_TIMER == 4
+# ifndef CONFIG_STM32_TIM4_DAC
+# error "CONFIG_STM32_TIM4_DAC required for DAC2"
+# endif
+# define DAC2_TSEL_VALUE DAC_CR_TSEL_TIM4
+# define DAC2_TIMER_BASE STM32_TIM4_BASE
+# define DAC2_TIMER_PCLK_FREQUENCY STM32_PCLK1_FREQUENCY
+# else
+# error "Unsupported CONFIG_STM32_DAC2_TIMER"
+# endif
+#else
+# define DAC2_TSEL_VALUE DAC_CR_TSEL_SW
+#endif
+
+/* Calculate timer divider values based upon DACn_TIMER_PCLK_FREQUENCY and
+ * CONFIG_STM32_DACn_TIMER_FREQUENCY.
+ */
+#warning "Missing Logic"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure represents the internal state of the single STM32 DAC block */
+
+struct stm32_dac_s
+{
+ uint8_t init : 1; /* True, the DAC block has been initialized */
+};
+
+/* This structure represents the internal state of one STM32 DAC channel */
+
+struct stm32_chan_s
+{
+ uint8_t inuse : 1; /* True, the driver is in use and not available */
+#ifdef HAVE_DMA
+ uint8_t hasdma : 1; /* True, this channel supports DMA */
+#endif
+ uint8_t intf; /* DAC zero-based interface number (0 or 1) */
+#ifdef HAVE_DMA
+ uint16_t dmachan; /* DMA channel needed by this DAC */
+ DMA_HANDLE dma; /* Allocated DMA channel */
+ uint32_t tsel; /* CR trigger select value */
+ uint32_t tbase; /* Timer base address */
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+/* DAC Register access */
+
+#ifdef HAVE_DMA
+static uint32_t tim_getreg(struct stm32_chan_s *chan, int offset);
+static void tim_putreg(struct stm32_chan_s *chan, int offset, uint32_t value);
+#endif
+
+/* Interrupt handler */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+static int dac_interrupt(int irq, void *context);
+#endif
+
+/* DAC methods */
+
+static void dac_reset(FAR struct dac_dev_s *dev);
+static int dac_setup(FAR struct dac_dev_s *dev);
+static void dac_shutdown(FAR struct dac_dev_s *dev);
+static void dac_txint(FAR struct dac_dev_s *dev, bool enable);
+static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg);
+static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg);
+static int dac_interrupt(int irq, void *context);
+
+/* Initialization */
+
+#ifdef HAVE_DMA
+static int dac_timinit(struct stm32_chan_s *chan);
+#endif
+static int dac_chaninit(struct stm32_chan_s *chan);
+static int dac_blockinit(void);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct dac_ops_s g_dacops =
+{
+ .ao_reset = dac_reset,
+ .ao_setup = dac_setup,
+ .ao_shutdown = dac_shutdown,
+ .ao_txint = dac_txint,
+ .ao_send = dac_send,
+ .ao_ioctl = dac_ioctl,
+};
+
+#ifdef CONFIG_STM32_DAC1
+static struct stm32_chan_s g_dac1priv =
+{
+ .intf = 0;
+#ifdef CONFIG_STM32_DAC1_DMA
+ .hasdma = 1;
+ .dmachan = DAC1_DMA_CHAN,
+ .tsel = DAC1_TSEL_VALUE,
+ .tbase = DAC1_TIMER_BASE
+#endif
+}
+
+static struct dac_dev_s g_dac1dev =
+{
+ .ad_ops = &g_dacops,
+ .ad_priv = &g_dac1priv,
+};
+#endif
+
+#ifdef CONFIG_STM32_DAC2
+static struct stm32_chan_s g_dac2priv =
+{
+ .intf = 1;
+#ifdef CONFIG_STM32_DAC2_DMA
+ .hasdma = 1;
+ .dmachan = DAC2_DMA_CHAN,
+ .tsel = DAC2_TSEL_VALUE.
+ .tbase = DAC2_TIMER_BASE
+#endif
+}
+
+static struct dac_dev_s g_dac2dev =
+{
+ .ad_ops = &g_dacops,
+ .ad_priv = &g_dac2priv,
+};
+#endif
+
+static struct stm32_dac_s g_dacblock;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: tim_getreg
+ *
+ * Description:
+ * Read the value of an DMA timer register.
+ *
+ * Input Parameters:
+ * chan - A reference to the DAC block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * The current contents of the specified register
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_DMA
+static uint32_t tim_getreg(struct stm32_chan_s *chan, int offset)
+{
+ return getreg32(chan->tbase + offset);
+}
+#endif
+
+/****************************************************************************
+ * Name: tim_putreg
+ *
+ * Description:
+ * Read the value of an DMA timer register.
+ *
+ * Input Parameters:
+ * chan - A reference to the DAC block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void tim_putreg(struct stm32_chan_s *chan, int offset, uint32_t value)
+{
+ putreg32(value, chan->tbase + offset);
+}
+#endif
+
+/****************************************************************************
+ * Name: dac_interrupt
+ *
+ * Description:
+ * DAC interrupt handler. The STM32 F4 family supports a only a DAC
+ * underrun interrupt.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ * OK
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+static int dac_interrupt(int irq, void *context)
+{
+#warning "Missing logic"
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: dac_reset
+ *
+ * Description:
+ * Reset the DAC channel. Called early to initialize the hardware. This
+ * is called, before dac_setup() and on error conditions.
+ *
+ * NOTE: DAC reset will reset both DAC channels!
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void dac_reset(FAR struct dac_dev_s *dev)
+{
+ irqstate_t flags;
+ uint32_t regval;
+
+ /* Reset only the selected DAC channel; the other DAC channel must remain
+ * functional.
+ */
+
+ flags = irqsave();
+
+#warning "Missing logic"
+
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: dac_setup
+ *
+ * Description:
+ * Configure the DAC. This method is called the first time that the DAC
+ * device is opened. This will occur when the port is first opened.
+ * This setup includes configuring and attaching DAC interrupts. Interrupts
+ * are all disabled upon return.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int dac_setup(FAR struct dac_dev_s *dev)
+{
+# warning "Missing logic"
+ return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: dac_shutdown
+ *
+ * Description:
+ * Disable the DAC. This method is called when the DAC device is closed.
+ * This method reverses the operation the setup method.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void dac_shutdown(FAR struct dac_dev_s *dev)
+{
+# warning "Missing logic"
+}
+
+/****************************************************************************
+ * Name: dac_txint
+ *
+ * Description:
+ * Call to enable or disable TX interrupts.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void dac_txint(FAR struct dac_dev_s *dev, bool enable)
+{
+# warning "Missing logic"
+}
+
+/****************************************************************************
+ * Name: dac_send
+ *
+ * Description:
+ * Set the DAC output.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg)
+{
+#ifdef HAVE_DMA
+ if (priv->hasdma)
+ {
+ /* Configure the DMA stream/channel.
+ *
+ * - Channel number
+ * - Peripheral address
+ * - Direction: Memory to peripheral
+ * - Disable peripheral address increment
+ * - Enable memory address increment
+ * - Peripheral data size: half word
+ * - Mode: circular???
+ * - Priority: ?
+ * - FIFO mode: disable
+ * - FIFO threshold: half full
+ * - Memory Burst: single
+ * - Peripheral Burst: single
+ */
+#warning "Missing logic"
+
+ /* Enable DMA */
+#warning "Missing logic"
+
+ /* Enable DAC Channel */
+#warning "Missing logic"
+
+ /* Enable DMA for DAC Channel */
+#warning "Missing logic"
+ }
+ else
+ {
+ /* Non-DMA transfer */
+#warning "Missing logic"
+ }
+ return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: dac_ioctl
+ *
+ * Description:
+ * All ioctl calls will be routed through this method.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg)
+{
+ return -ENOTTY;
+}
+
+/****************************************************************************
+ * Name: dac_timinit
+ *
+ * Description:
+ * Initialize the timer that drivers the DAC DMA for this channel using
+ * the pre-calculated timer divider definitions.
+ *
+ * Input Parameters:
+ * chan - A reference to the DAC channel state data
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_DMA
+static int dac_timinit(struct stm32_chan_s *chan)
+{
+ /* Configure the time base: Timer period, prescaler, clock division,
+ * counter mode (up).
+ */
+#warning "Missing Logic"
+
+ /* Selection TRGO selection: update */
+#warning "Missing Logic"
+
+ /* Enable the counter */
+#warning "Missing Logic"
+}
+#endif
+
+/****************************************************************************
+ * Name: dac_chaninit
+ *
+ * Description:
+ * Initialize the DAC channel.
+ *
+ * Input Parameters:
+ * chan - A reference to the DAC channel state data
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int dac_chaninit(struct stm32_chan_s *chan)
+{
+ /* Is the selected channel already in-use? */
+
+ if (chan->inuse)
+ {
+ /* Yes.. then return EBUSY */
+
+ return -EBUSY;
+ }
+
+ /* Configure the DAC output pin:
+ *
+ * DAC -" Once the DAC channelx is enabled, the corresponding GPIO pin
+ * (PA4 or PA5) is automatically connected to the analog converter output
+ * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin
+ * should first be configured to analog (AIN)".
+ */
+
+ stm32_configgpio(chan->intf ? GPIO_DAC2_OUT : GPIO_DAC1_OUT);
+
+ /* DAC channel configuration:
+ *
+ * - Set the trigger selection based upon the configuration.
+ * - Set wave generation == None.
+ * - Enable the output buffer.
+ */
+#warning "Missing logic"
+
+ /* Determine if DMA is supported by this channel */
+
+#ifdef HAVE_DMA
+ if (priv->hasdma)
+ {
+ /* Yes.. allocate a DMA channel */
+
+ priv->dma = stm32_dmachannel(priv->dmachan);
+ if (!priv->dma)
+ {
+ adbg("Failed to allocate a DMA channel\n");
+ return -EBUSY;
+ }
+
+ /* Configure the timer that supports the DMA operation */
+
+ ret = dac_timinit(chan);
+ if (ret < 0)
+ {
+ adbg("Failed to initialize the DMA timer: %d\n", ret);
+ return ret;
+ }
+ }
+#endif
+
+ /* Mark the DAC channel "in-use" */
+
+ chan->inuse = 1;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: dac_blockinit
+ *
+ * Description:
+ * All ioctl calls will be routed through this method.
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int dac_blockinit(void)
+{
+ irqstate_t flags;
+ uint32_t regval;
+
+ /* Has the DMA block already been initialized? */
+
+ if (g_dacblock.init)
+ {
+ /* Yes.. then return success We only have to do this once */
+
+ return OK;
+ }
+
+ /* Put the entire DAC block in reset state */
+
+ flags = irqsave();
+ regval = getreg32(STM32_RCC_APB1RSTR);
+ regval |= RCC_APB1RSTR_DACRST
+ putreg32(regval, STM32_RCC_APB1RSTR);
+
+ /* Take the DAC out of reset state */
+
+ regval &= ~RCC_APB1RSTR_DACRST
+ putreg32(regval, STM32_RCC_APB1RSTR);
+ irqrestore(flags);
+
+ /* Mark the DAC block as initialized */
+
+ g_dacblock.init = 1;
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_dacinitialize
+ *
+ * Description:
+ * Initialize the DAC.
+ *
+ * Input Parameters:
+ * intf - The DAC interface number.
+ *
+ * Returned Value:
+ * Valid dac device structure reference on succcess; a NULL on failure.
+ *
+ * Assumptions:
+ * 1. Clock to the DAC block has enabled,
+ * 2. Board-specific logic has already configured
+ *
+ ****************************************************************************/
+
+FAR struct dac_dev_s *stm32_dacinitialize(int intf)
+{
+ FAR struct dac_dev_s *dev;
+ FAR struct stm32_chan_s *chan;
+ int ret;
+
+#ifdef CONFIG_STM32_DAC1
+ if (intf == 1)
+ {
+ avdbg("DAC1 Selected\n");
+ dev = &g_dacdev1;
+ }
+ else
+#endif
+#ifdef CONFIG_STM32_DAC2
+ if (intf == 2)
+ {
+ avdbg("DAC2 Selected\n");
+ dev = &g_dac2dev;
+ }
+ else
+#endif
+ {
+ adbg("No such DAC interface: %d\n", intf);
+ return NULL;
+ }
+
+ /* Make sure that the DAC block has been initialized */
+
+ ret = dac_blockinit();
+ if (ret < 0)
+ {
+ adbg("Failed to initialize the DAC block: %d\n", ret);
+ return ret;
+ }
+
+ /* Configure the selected DAC channel */
+
+ chan = dev->ad_priv;
+ ret = dac_chaninit(chan);
+ if (ret < 0)
+ {
+ adbg("Failed to initialize DAC channel %d: %d\n", intf, ret);
+ return ret;
+ }
+
+ return dev;
+}
+
+#endif /* CONFIG_STM32_DAC1 || CONFIG_STM32_DAC2 */
+#endif /* CONFIG_DAC */
diff --git a/nuttx/arch/arm/src/stm32/stm32_dac.h b/nuttx/arch/arm/src/stm32/stm32_dac.h
new file mode 100644
index 000000000..44404e6fb
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_dac.h
@@ -0,0 +1,139 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_dac.h
+ *
+ * Copyright (C) 2011 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_STM32_STM32_DAC_H
+#define __ARCH_ARM_SRC_STM32_STM32_DAC_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_dac.h"
+
+#include <nuttx/analog/dac.h>
+
+/************************************************************************************
+ * Pre-processor definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* Timer devices may be used for different purposes. One special purpose is to
+ * control periodic DAC outputs. If CONFIG_STM32_TIMn is defined then
+ * CONFIG_STM32_TIMn_DAC must also be defined to indicate that timer "n" is intended
+ * to be used for that purpose.
+ */
+
+#ifndef CONFIG_STM32_TIM1
+# undef CONFIG_STM32_TIM1_DAC
+#endif
+#ifndef CONFIG_STM32_TIM2
+# undef CONFIG_STM32_TIM2_DAC
+#endif
+#ifndef CONFIG_STM32_TIM3
+# undef CONFIG_STM32_TIM3_DAC
+#endif
+#ifndef CONFIG_STM32_TIM4
+# undef CONFIG_STM32_TIM4_DAC
+#endif
+#ifndef CONFIG_STM32_TIM5
+# undef CONFIG_STM32_TIM5_DAC
+#endif
+#ifndef CONFIG_STM32_TIM6
+# undef CONFIG_STM32_TIM6_DAC
+#endif
+#ifndef CONFIG_STM32_TIM7
+# undef CONFIG_STM32_TIM7_DAC
+#endif
+#ifndef CONFIG_STM32_TIM8
+# undef CONFIG_STM32_TIM8_DAC
+#endif
+#ifndef CONFIG_STM32_TIM9
+# undef CONFIG_STM32_TIM9_DAC
+#endif
+#ifndef CONFIG_STM32_TIM10
+# undef CONFIG_STM32_TIM10_DAC
+#endif
+#ifndef CONFIG_STM32_TIM11
+# undef CONFIG_STM32_TIM11_DAC
+#endif
+#ifndef CONFIG_STM32_TIM12
+# undef CONFIG_STM32_TIM12_DAC
+#endif
+#ifndef CONFIG_STM32_TIM13
+# undef CONFIG_STM32_TIM13_DAC
+#endif
+#ifndef CONFIG_STM32_TIM14
+# undef CONFIG_STM32_TIM14_DAC
+#endif
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: stm32_dacinitialize
+ *
+ * Description:
+ * Initialize the DAC
+ *
+ * Input Parameters:
+ * intf - The DAC interface number.
+ *
+ * Returned Value:
+ * Valid dac device structure reference on succcess; a NULL on failure
+ *
+ ****************************************************************************/
+
+struct dac_dev_s;
+EXTERN FAR struct dac_dev_s *stm32_dacinitialize(int intf);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM_SRC_STM32_STM32_DAC_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_dbgmcu.h b/nuttx/arch/arm/src/stm32/stm32_dbgmcu.h
new file mode 100644
index 000000000..080f4bec5
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_dbgmcu.h
@@ -0,0 +1,64 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_dbgmcu.h
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_STM32_DBGMCU_H
+#define __ARCH_ARM_SRC_STM32_STM32_DBGMCU_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_dbgmcu.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_STM32_STM32_DBGMCU_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_dma.c b/nuttx/arch/arm/src/stm32/stm32_dma.c
new file mode 100644
index 000000000..0dd8eb94e
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_dma.c
@@ -0,0 +1,80 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_dma.c
+ *
+ * Copyright (C) 2009, 2011-2012 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 "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* This file is only a thin shell that includes the correct DMA implementation
+ * for the selected STM32 family. The correct file cannot be selected by
+ * the make system because it needs the intelligence that only exists in
+ * chip.h that can associate an STM32 part number with an STM32 family.
+ *
+ * The STM32 F4 DMA differs from the F1 DMA primarily in that it adds the
+ * concept of "streams" that are used to associate DMA sources with DMA
+ * channels.
+ */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "stm32f10xxx_dma.c"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "stm32f20xxx_dma.c"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "stm32f40xxx_dma.c"
+#endif
diff --git a/nuttx/arch/arm/src/stm32/stm32_dma.h b/nuttx/arch/arm/src/stm32/stm32_dma.h
new file mode 100644
index 000000000..cccbc41f0
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_dma.h
@@ -0,0 +1,309 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_dma.h
+ *
+ * Copyright (C) 2009, 2011-2012 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_STM32_STM32_DMA_H
+#define __ARCH_ARM_SRC_STM32_STM32_DMA_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+
+#include "chip.h"
+
+/* Include the correct DMA register definitions for this STM32 family */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "chip/stm32f10xxx_dma.h"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/stm32f20xxx_dma.h"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32f40xxx_dma.h"
+#else
+# error "Unknown STM32 DMA"
+#endif
+
+/* These definitions provide the bit encoding of the 'status' parameter passed to the
+ * DMA callback function (see dma_callback_t).
+ */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# define DMA_STATUS_FEIF 0 /* (Not available in F1) */
+# define DMA_STATUS_DMEIF 0 /* (Not available in F1) */
+# define DMA_STATUS_TEIF DMA_CHAN_TEIF_BIT /* Channel Transfer Error */
+# define DMA_STATUS_HTIF DMA_CHAN_HTIF_BIT /* Channel Half Transfer */
+# define DMA_STATUS_TCIF DMA_CHAN_TCIF_BIT /* Channel Transfer Complete */
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define DMA_STATUS_FEIF 0 /* Stream FIFO error (ignored) */
+# define DMA_STATUS_DMEIF DMA_STREAM_DMEIF_BIT /* Stream direct mode error */
+# define DMA_STATUS_TEIF DMA_STREAM_TEIF_BIT /* Stream Transfer Error */
+# define DMA_STATUS_HTIF DMA_STREAM_HTIF_BIT /* Stream Half Transfer */
+# define DMA_STATUS_TCIF DMA_STREAM_TCIF_BIT /* Stream Transfer Complete */
+#endif
+
+#define DMA_STATUS_ERROR (DMA_STATUS_FEIF|DMA_STATUS_DMEIF|DMA_STATUS_TEIF)
+#define DMA_STATUS_SUCCESS (DMA_STATUS_TCIF|DMA_STATUS_HTIF)
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/* DMA_HANDLE provides an opaque are reference that can be used to represent a DMA
+ * channel (F1) or a DMA stream (F4).
+ */
+
+typedef FAR void *DMA_HANDLE;
+
+/* Description:
+ * This is the type of the callback that is used to inform the user of the the
+ * completion of the DMA.
+ *
+ * Input Parameters:
+ * handle - Refers tot he DMA channel or stream
+ * status - A bit encoded value that provides the completion status. See the
+ * DMASTATUS_* definitions above.
+ * arg - A user-provided value that was provided when stm32_dmastart() was
+ * called.
+ */
+
+typedef void (*dma_callback_t)(DMA_HANDLE handle, uint8_t status, void *arg);
+
+#ifdef CONFIG_DEBUG_DMA
+#if defined(CONFIG_STM32_STM32F10XX)
+struct stm32_dmaregs_s
+{
+ uint32_t isr;
+ uint32_t ccr;
+ uint32_t cndtr;
+ uint32_t cpar;
+ uint32_t cmar;
+};
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+struct stm32_dmaregs_s
+{
+ uint32_t lisr;
+ uint32_t hisr;
+ uint32_t scr;
+ uint32_t sndtr;
+ uint32_t spar;
+ uint32_t sm0ar;
+ uint32_t sm1ar;
+ uint32_t sfcr;
+};
+#else
+# error "Unknown STM32 DMA"
+#endif
+#endif
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_dmachannel
+ *
+ * Description:
+ * Allocate a DMA channel. This function gives the caller mutually
+ * exclusive access to the DMA channel specified by the 'chan' argument.
+ * DMA channels are shared on the STM32: Devices sharing the same DMA
+ * channel cannot do DMA concurrently! See the DMACHAN_* definitions in
+ * stm32_dma.h.
+ *
+ * If the DMA channel is not available, then stm32_dmachannel() will wait
+ * until the holder of the channel relinquishes the channel by calling
+ * stm32_dmafree(). WARNING: If you have two devices sharing a DMA
+ * channel and the code never releases the channel, the stm32_dmachannel
+ * call for the other will hang forever in this function! Don't let your
+ * design do that!
+ *
+ * Hmm.. I suppose this interface could be extended to make a non-blocking
+ * version. Feel free to do that if that is what you need.
+ *
+ * Input parameter:
+ * chan - Identifies the stream/channel resource
+ * For the STM32 F1, this is simply the channel number as provided by
+ * the DMACHAN_* definitions in chip/stm32f10xxx_dma.h.
+ * For the STM32 F4, this is a bit encoded value as provided by the
+ * the DMAMAP_* definitions in chip/stm32f40xxx_dma.h
+ *
+ * Returned Value:
+ * Provided that 'chan' is valid, this function ALWAYS returns a non-NULL,
+ * void* DMA channel handle. (If 'chan' is invalid, the function will
+ * assert if debug is enabled or do something ignorant otherwise).
+ *
+ * Assumptions:
+ * - The caller does not hold he DMA channel.
+ * - The caller can wait for the DMA channel to be freed if it is no
+ * available.
+ *
+ ****************************************************************************/
+
+EXTERN DMA_HANDLE stm32_dmachannel(unsigned int chan);
+
+/****************************************************************************
+ * Name: stm32_dmafree
+ *
+ * Description:
+ * Release a DMA channel. If another thread is waiting for this DMA channel
+ * in a call to stm32_dmachannel, then this function will re-assign the
+ * DMA channel to that thread and wake it up. NOTE: The 'handle' used
+ * in this argument must NEVER be used again until stm32_dmachannel() is
+ * called again to re-gain access to the channel.
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * - The caller holds the DMA channel.
+ * - There is no DMA in progress
+ *
+ ****************************************************************************/
+
+EXTERN void stm32_dmafree(DMA_HANDLE handle);
+
+/****************************************************************************
+ * Name: stm32_dmasetup
+ *
+ * Description:
+ * Configure DMA before using
+ *
+ ****************************************************************************/
+
+EXTERN void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
+ size_t ntransfers, uint32_t ccr);
+
+/****************************************************************************
+ * Name: stm32_dmastart
+ *
+ * Description:
+ * Start the DMA transfer
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ * - No DMA in progress
+ *
+ ****************************************************************************/
+
+EXTERN void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback,
+ void *arg, bool half);
+
+/****************************************************************************
+ * Name: stm32_dmastop
+ *
+ * Description:
+ * Cancel the DMA. After stm32_dmastop() is called, the DMA channel is
+ * reset and stm32_dmasetup() must be called before stm32_dmastart() can be
+ * called again
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+EXTERN void stm32_dmastop(DMA_HANDLE handle);
+
+/****************************************************************************
+ * Name: stm32_dmaresidual
+ *
+ * Description:
+ * Returns the number of bytes remaining to be transferred
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+EXTERN size_t stm32_dmaresidual(DMA_HANDLE handle);
+
+/****************************************************************************
+ * Name: stm32_dmasample
+ *
+ * Description:
+ * Sample DMA register contents
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_DMA
+EXTERN void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs);
+#else
+# define stm32_dmasample(handle,regs)
+#endif
+
+/****************************************************************************
+ * Name: stm32_dmadump
+ *
+ * Description:
+ * Dump previously sampled DMA register contents
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_DMA
+EXTERN void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs,
+ const char *msg);
+#else
+# define stm32_dmadump(handle,regs,msg)
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_DMA_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_dumpgpio.c b/nuttx/arch/arm/src/stm32/stm32_dumpgpio.c
new file mode 100644
index 000000000..cd1933831
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_dumpgpio.c
@@ -0,0 +1,179 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_gpio.c
+ *
+ * Copyright (C) 2009, 2011 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 <debug.h>
+
+#include "up_arch.h"
+
+#include "chip.h"
+#include "stm32_gpio.h"
+#include "stm32_rcc.h"
+
+#ifdef CONFIG_DEBUG
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+/* Port letters for prettier debug output */
+
+#ifdef CONFIG_DEBUG
+static const char g_portchar[STM32_NGPIO_PORTS] =
+{
+#if STM32_NGPIO_PORTS > 9
+# error "Additional support required for this number of GPIOs"
+#elif STM32_NGPIO_PORTS > 8
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'
+#elif STM32_NGPIO_PORTS > 7
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'
+#elif STM32_NGPIO_PORTS > 6
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G'
+#elif STM32_NGPIO_PORTS > 5
+ 'A', 'B', 'C', 'D', 'E', 'F'
+#elif STM32_NGPIO_PORTS > 4
+ 'A', 'B', 'C', 'D', 'E'
+#elif STM32_NGPIO_PORTS > 3
+ 'A', 'B', 'C', 'D'
+#elif STM32_NGPIO_PORTS > 2
+ 'A', 'B', 'C'
+#elif STM32_NGPIO_PORTS > 1
+ 'A', 'B'
+#elif STM32_NGPIO_PORTS > 0
+ 'A'
+#else
+# error "Bad number of GPIOs"
+#endif
+};
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: stm32_dumpgpio
+ *
+ * Description:
+ * Dump all GPIO registers associated with the provided base address
+ *
+ ****************************************************************************/
+
+int stm32_dumpgpio(uint32_t pinset, const char *msg)
+{
+ irqstate_t flags;
+ uint32_t base;
+ unsigned int port;
+ unsigned int pin;
+
+ /* Get the base address associated with the GPIO port */
+
+ port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+ pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+ base = g_gpiobase[port];
+
+ /* The following requires exclusive access to the GPIO registers */
+
+ flags = irqsave();
+#if defined(CONFIG_STM32_STM32F10XX)
+ lldbg("GPIO%c pinset: %08x base: %08x -- %s\n",
+ g_portchar[port], pinset, base, msg);
+ if ((getreg32(STM32_RCC_APB2ENR) & RCC_APB2ENR_IOPEN(port)) != 0)
+ {
+ lldbg(" CR: %08x %08x IDR: %04x ODR: %04x LCKR: %04x\n",
+ getreg32(base + STM32_GPIO_CRH_OFFSET),
+ getreg32(base + STM32_GPIO_CRL_OFFSET),
+ getreg32(base + STM32_GPIO_IDR_OFFSET),
+ getreg32(base + STM32_GPIO_ODR_OFFSET),
+ getreg32(base + STM32_GPIO_LCKR_OFFSET));
+ lldbg(" EVCR: %02x MAPR: %08x CR: %04x %04x %04x %04x\n",
+ getreg32(STM32_AFIO_EVCR), getreg32(STM32_AFIO_MAPR),
+ getreg32(STM32_AFIO_EXTICR1),
+ getreg32(STM32_AFIO_EXTICR2),
+ getreg32(STM32_AFIO_EXTICR3),
+ getreg32(STM32_AFIO_EXTICR4));
+ }
+ else
+ {
+ lldbg(" GPIO%c not enabled: APB2ENR: %08x\n",
+ g_portchar[port], getreg32(STM32_RCC_APB2ENR));
+ }
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ DEBUGASSERT(port < STM32_NGPIO_PORTS);
+
+ lldbg("GPIO%c pinset: %08x base: %08x -- %s\n",
+ g_portchar[port], pinset, base, msg);
+ if ((getreg32(STM32_RCC_AHB1ENR) & RCC_AHB1ENR_GPIOEN(port)) != 0)
+ {
+ lldbg(" MODE: %08x OTYPE: %04x OSPEED: %08x PUPDR: %08x\n",
+ getreg32(base + STM32_GPIO_MODER_OFFSET),
+ getreg32(base + STM32_GPIO_OTYPER_OFFSET),
+ getreg32(base + STM32_GPIO_OSPEED_OFFSET),
+ getreg32(base + STM32_GPIO_PUPDR_OFFSET));
+ lldbg(" IDR: %04x ODR: %04x BSRR: %08x LCKR: %04x\n",
+ getreg32(base + STM32_GPIO_IDR_OFFSET),
+ getreg32(base + STM32_GPIO_ODR_OFFSET),
+ getreg32(base + STM32_GPIO_BSRR_OFFSET),
+ getreg32(base + STM32_GPIO_LCKR_OFFSET));
+ lldbg(" AFRH: %08x AFRL: %08x\n",
+ getreg32(base + STM32_GPIO_ARFH_OFFSET),
+ getreg32(base + STM32_GPIO_AFRL_OFFSET));
+ }
+ else
+ {
+ lldbg(" GPIO%c not enabled: AHB1ENR: %08x\n",
+ g_portchar[port], getreg32(STM32_RCC_AHB1ENR));
+ }
+#else
+# error "Unsupported STM32 chip"
+#endif
+ irqrestore(flags);
+ return OK;
+}
+
+#endif /* CONFIG_DEBUG */
diff --git a/nuttx/arch/arm/src/stm32/stm32_eth.c b/nuttx/arch/arm/src/stm32/stm32_eth.c
new file mode 100644
index 000000000..68ee78fd5
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_eth.c
@@ -0,0 +1,3109 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_eth.c
+ *
+ * Copyright (C) 2011-2012 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>
+#if defined(CONFIG_NET) && defined(CONFIG_STM32_ETHMAC)
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <string.h>
+#include <debug.h>
+#include <wdog.h>
+#include <queue.h>
+#include <errno.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/net/mii.h>
+
+#include <nuttx/net/uip/uip.h>
+#include <nuttx/net/uip/uip-arp.h>
+#include <nuttx/net/uip/uip-arch.h>
+
+#include "up_internal.h"
+
+#include "chip.h"
+#include "stm32_gpio.h"
+#include "stm32_rcc.h"
+#include "stm32_syscfg.h"
+#include "stm32_eth.h"
+
+#include <arch/board/board.h>
+
+/* STM32_NETHERNET determines the number of physical interfaces
+ * that will be supported.
+ */
+
+#if STM32_NETHERNET > 0
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+/* See configs/stm3240g-eval/README.txt for an explanation of the configuration
+ * settings.
+ */
+
+#if STM32_NETHERNET > 1
+# error "Logic to support multiple Ethernet interfaces is incomplete"
+#endif
+
+#ifndef CONFIG_STM32_SYSCFG
+# error "CONFIG_STM32_SYSCFG must be defined in the NuttX configuration"
+#endif
+
+#ifndef CONFIG_STM32_PHYADDR
+# error "CONFIG_STM32_PHYADDR must be defined in the NuttX configuration"
+#endif
+
+#if !defined(CONFIG_STM32_MII) && !defined(CONFIG_STM32_RMII)
+# warning "Neither CONFIG_STM32_MII nor CONFIG_STM32_RMII defined"
+#endif
+
+#if defined(CONFIG_STM32_MII) && defined(CONFIG_STM32_RMII)
+# error "Both CONFIG_STM32_MII and CONFIG_STM32_RMII defined"
+#endif
+
+#ifdef CONFIG_STM32_MII
+# if !defined(CONFIG_STM32_MII_MCO1) && !defined(CONFIG_STM32_MII_MCO2)
+# warning "Neither CONFIG_STM32_MII_MCO1 nor CONFIG_STM32_MII_MCO2 defined"
+# endif
+# if defined(CONFIG_STM32_MII_MCO1) && defined(CONFIG_STM32_MII_MCO2)
+# error "Both CONFIG_STM32_MII_MCO1 and CONFIG_STM32_MII_MCO2 defined"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_AUTONEG
+# ifndef CONFIG_STM32_PHYSR
+# error "CONFIG_STM32_PHYSR must be defined in the NuttX configuration"
+# endif
+# ifndef CONFIG_STM32_PHYSR_SPEED
+# error "CONFIG_STM32_PHYSR_SPEED must be defined in the NuttX configuration"
+# endif
+# ifndef CONFIG_STM32_PHYSR_100MBPS
+# error "CONFIG_STM32_PHYSR_100MBPS must be defined in the NuttX configuration"
+# endif
+# ifndef CONFIG_STM32_PHYSR_MODE
+# error "CONFIG_STM32_PHYSR_MODE must be defined in the NuttX configuration"
+# endif
+# ifndef CONFIG_STM32_PHYSR_FULLDUPLEX
+# error "CONFIG_STM32_PHYSR_FULLDUPLEX must be defined in the NuttX configuration"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_ETH_PTP
+# warning "CONFIG_STM32_ETH_PTP is not yet supported"
+#endif
+
+/* This driver does not use enhanced descriptors. Enhanced descriptors must
+ * be used, however, if time stamping or and/or IPv4 checksum offload is
+ * supported.
+ */
+
+#undef CONFIG_STM32_ETH_ENHANCEDDESC
+#undef CONFIG_STM32_ETH_HWCHECKSUM
+
+/* Ethernet buffer sizes, number of buffers, and number of descriptors */
+
+#ifndef CONFIG_NET_MULTIBUFFER
+# error "CONFIG_NET_MULTIBUFFER is required"
+#endif
+
+/* Add 4 to the configured buffer size to account for the 2 byte checksum
+ * memory needed at the end of the maximum size packet.
+ */
+
+#define OPTIMAL_ETH_BUFSIZE (CONFIG_NET_BUFSIZE+4)
+
+#ifndef CONFIG_STM32_ETH_BUFSIZE
+# define CONFIG_STM32_ETH_BUFSIZE OPTIMAL_ETH_BUFSIZE
+#endif
+
+#if CONFIG_STM32_ETH_BUFSIZE > ETH_TDES1_TBS1_MASK
+# error "CONFIG_STM32_ETH_BUFSIZE is too large"
+#endif
+
+#if CONFIG_STM32_ETH_BUFSIZE != OPTIMAL_ETH_BUFSIZE
+# warning "You using an incomplete/untested configuration"
+#endif
+
+#ifndef CONFIG_STM32_ETH_NRXDESC
+# define CONFIG_STM32_ETH_NRXDESC 8
+#endif
+#ifndef CONFIG_STM32_ETH_NTXDESC
+# define CONFIG_STM32_ETH_NTXDESC 4
+#endif
+
+/* We need at least one more free buffer than transmit buffers */
+
+#define STM32_ETH_NFREEBUFFERS (CONFIG_STM32_ETH_NTXDESC+1)
+
+/* Extremely detailed register debug that you would normally never want
+ * enabled.
+ */
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_STM32_ETHMAC_REGDEBUG
+#endif
+
+/* Clocking *****************************************************************/
+/* Set MACMIIAR CR bits depending on HCLK setting */
+
+#if STM32_HCLK_FREQUENCY >= 20000000 && STM32_HCLK_FREQUENCY < 35000000
+# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_20_35
+#elif STM32_HCLK_FREQUENCY >= 35000000 && STM32_HCLK_FREQUENCY < 60000000
+# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_35_60
+#elif STM32_HCLK_FREQUENCY >= 60000000 && STM32_HCLK_FREQUENCY < 100000000
+# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_60_100
+#elif STM32_HCLK_FREQUENCY >= 100000000 && STM32_HCLK_FREQUENCY < 150000000
+# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_100_150
+#elif STM32_HCLK_FREQUENCY >= 150000000 && STM32_HCLK_FREQUENCY <= 168000000
+# define ETH_MACMIIAR_CR ETH_MACMIIAR_CR_150_168
+#else
+# error "STM32_HCLK_FREQUENCY not supportable"
+#endif
+
+/* Timing *******************************************************************/
+/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per
+ * second
+ */
+
+#define STM32_WDDELAY (1*CLK_TCK)
+#define STM32_POLLHSEC (1*2)
+
+/* TX timeout = 1 minute */
+
+#define STM32_TXTIMEOUT (60*CLK_TCK)
+
+/* PHY reset/configuration delays in milliseconds */
+
+#define PHY_RESET_DELAY (65)
+#define PHY_CONFIG_DELAY (1000)
+
+/* PHY read/write delays in loop counts */
+
+#define PHY_READ_TIMEOUT (0x0004ffff)
+#define PHY_WRITE_TIMEOUT (0x0004ffff)
+#define PHY_RETRY_TIMEOUT (0x0004ffff)
+
+/* Register values **********************************************************/
+
+/* Clear the MACCR bits that will be setup during MAC initialization (or that
+ * are cleared unconditionally). Per the reference manual, all reserved bits
+ * must be retained at their reset value.
+ *
+ * ETH_MACCR_RE Bit 2: Receiver enable
+ * ETH_MACCR_TE Bit 3: Transmitter enable
+ * ETH_MACCR_DC Bit 4: Deferral check
+ * ETH_MACCR_BL Bits 5-6: Back-off limit
+ * ETH_MACCR_APCS Bit 7: Automatic pad/CRC stripping
+ * ETH_MACCR_RD Bit 9: Retry disable
+ * ETH_MACCR_IPCO Bit 10: IPv4 checksum offload
+ * ETH_MACCR_DM Bit 11: Duplex mode
+ * ETH_MACCR_LM Bit 12: Loopback mode
+ * ETH_MACCR_ROD Bit 13: Receive own disable
+ * ETH_MACCR_FES Bit 14: Fast Ethernet speed
+ * ETH_MACCR_CSD Bit 16: Carrier sense disable
+ * ETH_MACCR_IFG Bits 17-19: Interframe gap
+ * ETH_MACCR_JD Bit 22: Jabber disable
+ * ETH_MACCR_WD Bit 23: Watchdog disable
+ * ETH_MACCR_CSTF Bits 25: CRC stripping for Type frames
+ */
+
+#define MACCR_CLEAR_BITS \
+ ( ETH_MACCR_RE | ETH_MACCR_TE | ETH_MACCR_DC | ETH_MACCR_BL_MASK | \
+ ETH_MACCR_APCS | ETH_MACCR_RD | ETH_MACCR_IPCO | ETH_MACCR_DM | \
+ ETH_MACCR_LM | ETH_MACCR_ROD | ETH_MACCR_FES | ETH_MACCR_CSD | \
+ ETH_MACCR_IFG_MASK | ETH_MACCR_JD | ETH_MACCR_WD | ETH_MACCR_CSTF )
+
+/* The following bits are set or left zero unconditionally in all modes.
+ *
+ * ETH_MACCR_RE Receiver enable 0 (disabled)
+ * ETH_MACCR_TE Transmitter enable 0 (disabled)
+ * ETH_MACCR_DC Deferral check 0 (disabled)
+ * ETH_MACCR_BL Back-off limit 0 (10)
+ * ETH_MACCR_APCS Automatic pad/CRC stripping 0 (disabled)
+ * ETH_MACCR_RD Retry disable 1 (disabled)
+ * ETH_MACCR_IPCO IPv4 checksum offload Depends on CONFIG_STM32_ETH_HWCHECKSUM
+ * ETH_MACCR_LM Loopback mode 0 (disabled)
+ * ETH_MACCR_ROD Receive own disable 0 (enabled)
+ * ETH_MACCR_CSD Carrier sense disable 0 (enabled)
+ * ETH_MACCR_IFG Interframe gap 0 (96 bits)
+ * ETH_MACCR_JD Jabber disable 0 (enabled)
+ * ETH_MACCR_WD Watchdog disable 0 (enabled)
+ * ETH_MACCR_CSTF CRC stripping for Type frames 0 (disabled)
+ *
+ * The following are set conditioinally based on mode and speed.
+ *
+ * ETH_MACCR_DM Duplex mode Depends on priv->fduplex
+ * ETH_MACCR_FES Fast Ethernet speed Depends on priv->mbps100
+ */
+
+#ifdef CONFIG_STM32_ETH_HWCHECKSUM
+# define MACCR_SET_BITS \
+ (ETH_MACCR_BL_10 | ETH_MACCR_RD | ETH_MACCR_IPCO | ETH_MACCR_IFG(96))
+#else
+# define MACCR_SET_BITS \
+ (ETH_MACCR_BL_10 | ETH_MACCR_RD | ETH_MACCR_IFG(96))
+#endif
+
+/* Clear the MACCR bits that will be setup during MAC initialization (or that
+ * are cleared unconditionally). Per the reference manual, all reserved bits
+ * must be retained at their reset value.
+ *
+ * ETH_MACFFR_PM Bit 0: Promiscuous mode
+ * ETH_MACFFR_HU Bit 1: Hash unicast
+ * ETH_MACFFR_HM Bit 2: Hash multicast
+ * ETH_MACFFR_DAIF Bit 3: Destination address inverse filtering
+ * ETH_MACFFR_PAM Bit 4: Pass all multicast
+ * ETH_MACFFR_BFD Bit 5: Broadcast frames disable
+ * ETH_MACFFR_PCF Bits 6-7: Pass control frames
+ * ETH_MACFFR_SAIF Bit 8: Source address inverse filtering
+ * ETH_MACFFR_SAF Bit 9: Source address filter
+ * ETH_MACFFR_HPF Bit 10: Hash or perfect filter
+ * ETH_MACFFR_RA Bit 31: Receive all
+ */
+
+#define MACFFR_CLEAR_BITS \
+ (ETH_MACFFR_PM | ETH_MACFFR_HU | ETH_MACFFR_HM | ETH_MACFFR_DAIF | \
+ ETH_MACFFR_PAM | ETH_MACFFR_BFD | ETH_MACFFR_PCF_MASK | ETH_MACFFR_SAIF | \
+ ETH_MACFFR_SAF | ETH_MACFFR_HPF | ETH_MACFFR_RA)
+
+/* The following bits are set or left zero unconditionally in all modes.
+ *
+ * ETH_MACFFR_PM Promiscuous mode 0 (disabled)
+ * ETH_MACFFR_HU Hash unicast 0 (perfect dest filtering)
+ * ETH_MACFFR_HM Hash multicast 0 (perfect dest filtering)
+ * ETH_MACFFR_DAIF Destination address inverse filtering 0 (normal)
+ * ETH_MACFFR_PAM Pass all multicast 0 (Depends on HM bit)
+ * ETH_MACFFR_BFD Broadcast frames disable 0 (enabled)
+ * ETH_MACFFR_PCF Pass control frames 1 (block all but PAUSE)
+ * ETH_MACFFR_SAIF Source address inverse filtering 0 (not used)
+ * ETH_MACFFR_SAF Source address filter 0 (disabled)
+ * ETH_MACFFR_HPF Hash or perfect filter 0 (Only matching frames passed)
+ * ETH_MACFFR_RA Receive all 0 (disabled)
+ */
+
+#define MACFFR_SET_BITS (ETH_MACFFR_PCF_PAUSE)
+
+/* Clear the MACFCR bits that will be setup during MAC initialization (or that
+ * are cleared unconditionally). Per the reference manual, all reserved bits
+ * must be retained at their reset value.
+ *
+ * ETH_MACFCR_FCB_BPA Bit 0: Flow control busy/back pressure activate
+ * ETH_MACFCR_TFCE Bit 1: Transmit flow control enable
+ * ETH_MACFCR_RFCE Bit 2: Receive flow control enable
+ * ETH_MACFCR_UPFD Bit 3: Unicast pause frame detect
+ * ETH_MACFCR_PLT Bits 4-5: Pause low threshold
+ * ETH_MACFCR_ZQPD Bit 7: Zero-quanta pause disable
+ * ETH_MACFCR_PT Bits 16-31: Pause time
+ */
+
+#define MACFCR_CLEAR_MASK \
+ (ETH_MACFCR_FCB_BPA | ETH_MACFCR_TFCE | ETH_MACFCR_RFCE | ETH_MACFCR_UPFD | \
+ ETH_MACFCR_PLT_MASK | ETH_MACFCR_ZQPD | ETH_MACFCR_PT_MASK)
+
+/* The following bits are set or left zero unconditionally in all modes.
+ *
+ * ETH_MACFCR_FCB_BPA Flow control busy/back pressure activate 0 (no pause control frame)
+ * ETH_MACFCR_TFCE Transmit flow control enable 0 (disabled)
+ * ETH_MACFCR_RFCE Receive flow control enable 0 (disabled)
+ * ETH_MACFCR_UPFD Unicast pause frame detect 0 (disabled)
+ * ETH_MACFCR_PLT Pause low threshold 0 (pause time - 4)
+ * ETH_MACFCR_ZQPD Zero-quanta pause disable 1 (disabled)
+ * ETH_MACFCR_PT Pause time 0
+ */
+
+#define MACFCR_SET_MASK (ETH_MACFCR_PLT_M4 | ETH_MACFCR_ZQPD)
+
+/* Clear the DMAOMR bits that will be setup during MAC initialization (or that
+ * are cleared unconditionally). Per the reference manual, all reserved bits
+ * must be retained at their reset value.
+ *
+ * ETH_DMAOMR_SR Bit 1: Start/stop receive
+ * TH_DMAOMR_OSF Bit 2: Operate on second frame
+ * ETH_DMAOMR_RTC Bits 3-4: Receive threshold control
+ * ETH_DMAOMR_FUGF Bit 6: Forward undersized good frames
+ * ETH_DMAOMR_FEF Bit 7: Forward error frames
+ * ETH_DMAOMR_ST Bit 13: Start/stop transmission
+ * ETH_DMAOMR_TTC Bits 14-16: Transmit threshold control
+ * ETH_DMAOMR_FTF Bit 20: Flush transmit FIFO
+ * ETH_DMAOMR_TSF Bit 21: Transmit store and forward
+ * ETH_DMAOMR_DFRF Bit 24: Disable flushing of received frames
+ * ETH_DMAOMR_RSF Bit 25: Receive store and forward
+ * TH_DMAOMR_DTCEFD Bit 26: Dropping of TCP/IP checksum error frames disable
+ */
+
+#define DMAOMR_CLEAR_MASK \
+ (ETH_DMAOMR_SR | ETH_DMAOMR_OSF | ETH_DMAOMR_RTC_MASK | ETH_DMAOMR_FUGF | \
+ ETH_DMAOMR_FEF | ETH_DMAOMR_ST | ETH_DMAOMR_TTC_MASK | ETH_DMAOMR_FTF | \
+ ETH_DMAOMR_TSF | ETH_DMAOMR_DFRF | ETH_DMAOMR_RSF | ETH_DMAOMR_DTCEFD)
+
+/* The following bits are set or left zero unconditionally in all modes.
+ *
+ * ETH_DMAOMR_SR Start/stop receive 0 (not running)
+ * TH_DMAOMR_OSF Operate on second frame 1 (enabled)
+ * ETH_DMAOMR_RTC Receive threshold control 0 (64 bytes)
+ * ETH_DMAOMR_FUGF Forward undersized good frames 0 (disabled)
+ * ETH_DMAOMR_FEF Forward error frames 0 (disabled)
+ * ETH_DMAOMR_ST Start/stop transmission 0 (not running)
+ * ETH_DMAOMR_TTC Transmit threshold control 0 (64 bytes)
+ * ETH_DMAOMR_FTF Flush transmit FIFO 0 (no flush)
+ * ETH_DMAOMR_TSF Transmit store and forward Depends on CONFIG_STM32_ETH_HWCHECKSUM
+ * ETH_DMAOMR_DFRF Disable flushing of received frames 0 (enabled)
+ * ETH_DMAOMR_RSF Receive store and forward Depends on CONFIG_STM32_ETH_HWCHECKSUM
+ * TH_DMAOMR_DTCEFD Dropping of TCP/IP checksum error Depends on CONFIG_STM32_ETH_HWCHECKSUM
+ * frames disable
+ *
+ * When the checksum offload feature is enabled, we need to enable the Store
+ * and Forward mode: the store and forward guarantee that a whole frame is
+ * stored in the FIFO, so the MAC can insert/verify the checksum, if the
+ * checksum is OK the DMA can handle the frame otherwise the frame is dropped
+ */
+
+#if CONFIG_STM32_ETH_HWCHECKSUM
+# define DMAOMR_SET_MASK \
+ (ETH_DMAOMR_OSF | ETH_DMAOMR_RTC_64 | ETH_DMAOMR_TTC_64 | \
+ ETH_DMAOMR_TSF | ETH_DMAOMR_RSF)
+#else
+# define DMAOMR_SET_MASK \
+ (ETH_DMAOMR_OSF | ETH_DMAOMR_RTC_64 | ETH_DMAOMR_TTC_64 | \
+ ETH_DMAOMR_DTCEFD)
+#endif
+
+/* Clear the DMABMR bits that will be setup during MAC initialization (or that
+ * are cleared unconditionally). Per the reference manual, all reserved bits
+ * must be retained at their reset value.
+ *
+ * ETH_DMABMR_SR Bit 0: Software reset
+ * ETH_DMABMR_DA Bit 1: DMA Arbitration
+ * ETH_DMABMR_DSL Bits 2-6: Descriptor skip length
+ * ETH_DMABMR_EDFE Bit 7: Enhanced descriptor format enable
+ * ETH_DMABMR_PBL Bits 8-13: Programmable burst length
+ * ETH_DMABMR_RTPR Bits 14-15: RX TX priority ratio
+ * ETH_DMABMR_FB Bit 16: Fixed burst
+ * ETH_DMABMR_RDP Bits 17-22: RX DMA PBL
+ * ETH_DMABMR_USP Bit 23: Use separate PBL
+ * ETH_DMABMR_FPM Bit 24: 4xPBL mode
+ * ETH_DMABMR_AAB Bit 25: Address-aligned beats
+ * ETH_DMABMR_MB Bit 26: Mixed burst
+ */
+
+#define DMABMR_CLEAR_MASK \
+ (ETH_DMABMR_SR | ETH_DMABMR_DA | ETH_DMABMR_DSL_MASK | ETH_DMABMR_EDFE | \
+ ETH_DMABMR_PBL_MASK | ETH_DMABMR_RTPR_MASK | ETH_DMABMR_FB | ETH_DMABMR_RDP_MASK | \
+ ETH_DMABMR_USP | ETH_DMABMR_FPM | ETH_DMABMR_AAB | ETH_DMABMR_MB)
+
+/* The following bits are set or left zero unconditionally in all modes.
+ *
+ *
+ * ETH_DMABMR_SR Software reset 0 (no reset)
+ * ETH_DMABMR_DA DMA Arbitration 0 (round robin)
+ * ETH_DMABMR_DSL Descriptor skip length 0
+ * ETH_DMABMR_EDFE Enhanced descriptor format enable Depends on CONFIG_STM32_ETH_ENHANCEDDESC
+ * ETH_DMABMR_PBL Programmable burst length 32 beats
+ * ETH_DMABMR_RTPR RX TX priority ratio 2:1
+ * ETH_DMABMR_FB Fixed burst 1 (enabled)
+ * ETH_DMABMR_RDP RX DMA PBL 32 beats
+ * ETH_DMABMR_USP Use separate PBL 1 (enabled)
+ * ETH_DMABMR_FPM 4xPBL mode 0 (disabled)
+ * ETH_DMABMR_AAB Address-aligned beats 1 (enabled)
+ * ETH_DMABMR_MB Mixed burst 0 (disabled)
+ */
+
+#ifdef CONFIG_STM32_ETH_ENHANCEDDESC
+# define DMABMR_SET_MASK \
+ (ETH_DMABMR_DSL(0) | ETH_DMABMR_PBL(32) | ETH_DMABMR_EDFE | ETH_DMABMR_RTPR_2TO1 | \
+ ETH_DMABMR_FB | ETH_DMABMR_RDP(32) | ETH_DMABMR_USP | ETH_DMABMR_AAB)
+#else
+# define DMABMR_SET_MASK \
+ (ETH_DMABMR_DSL(0) | ETH_DMABMR_PBL(32) | ETH_DMABMR_RTPR_2TO1 | ETH_DMABMR_FB | \
+ ETH_DMABMR_RDP(32) | ETH_DMABMR_USP | ETH_DMABMR_AAB)
+#endif
+
+/* Interrupt bit sets *******************************************************/
+/* All interrupts in the normal and abnormal interrupt summary. Early transmit
+ * interrupt (ETI) is excluded from the abnormal set because it causes too
+ * many interrupts and is not interesting.
+ */
+
+#define ETH_DMAINT_NORMAL \
+ (ETH_DMAINT_TI | ETH_DMAINT_TBUI |ETH_DMAINT_RI | ETH_DMAINT_ERI)
+
+#define ETH_DMAINT_ABNORMAL \
+ (ETH_DMAINT_TPSI | ETH_DMAINT_TJTI | ETH_DMAINT_ROI | ETH_DMAINT_TUI | \
+ ETH_DMAINT_RBUI | ETH_DMAINT_RPSI | ETH_DMAINT_RWTI | /* ETH_DMAINT_ETI | */ \
+ ETH_DMAINT_FBEI)
+
+/* Normal receive, transmit, error interrupt enable bit sets */
+
+#define ETH_DMAINT_RECV_ENABLE (ETH_DMAINT_NIS | ETH_DMAINT_RI)
+#define ETH_DMAINT_XMIT_ENABLE (ETH_DMAINT_NIS | ETH_DMAINT_TI)
+#define ETH_DMAINT_XMIT_DISABLE (ETH_DMAINT_TI)
+
+#ifdef CONFIG_DEBUG_NET
+# define ETH_DMAINT_ERROR_ENABLE (ETH_DMAINT_AIS | ETH_DMAINT_ABNORMAL)
+#else
+# define ETH_DMAINT_ERROR_ENABLE (0)
+#endif
+
+/* Helpers ******************************************************************/
+/* This is a helper pointer for accessing the contents of the Ethernet
+ * header
+ */
+
+#define BUF ((struct uip_eth_hdr *)priv->dev.d_buf)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* The stm32_ethmac_s encapsulates all state information for a single hardware
+ * interface
+ */
+
+struct stm32_ethmac_s
+{
+ uint8_t ifup : 1; /* true:ifup false:ifdown */
+ uint8_t mbps100 : 1; /* 100MBps operation (vs 10 MBps) */
+ uint8_t fduplex : 1; /* Full (vs. half) duplex */
+ WDOG_ID txpoll; /* TX poll timer */
+ WDOG_ID txtimeout; /* TX timeout timer */
+
+ /* This holds the information visible to uIP/NuttX */
+
+ struct uip_driver_s dev; /* Interface understood by uIP */
+
+ /* Used to track transmit and receive descriptors */
+
+ struct eth_txdesc_s *txhead; /* Next available TX descriptor */
+ struct eth_rxdesc_s *rxhead; /* Next available RX descriptor */
+
+ struct eth_txdesc_s *txtail; /* First "in_flight" TX descriptor */
+ struct eth_rxdesc_s *rxcurr; /* First RX descriptor of the segment */
+ uint16_t segments; /* RX segment count */
+ uint16_t inflight; /* Number of TX transfers "in_flight" */
+ sq_queue_t freeb; /* The free buffer list */
+
+ /* Descriptor allocations */
+
+ struct eth_rxdesc_s rxtable[CONFIG_STM32_ETH_NRXDESC];
+ struct eth_txdesc_s txtable[CONFIG_STM32_ETH_NTXDESC];
+
+ /* Buffer allocations */
+
+ uint8_t rxbuffer[CONFIG_STM32_ETH_NRXDESC*CONFIG_STM32_ETH_BUFSIZE];
+ uint8_t alloc[STM32_ETH_NFREEBUFFERS*CONFIG_STM32_ETH_BUFSIZE];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct stm32_ethmac_s g_stm32ethmac[STM32_NETHERNET];
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+/* Register operations ******************************************************/
+
+#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint32_t stm32_getreg(uint32_t addr);
+static void stm32_putreg(uint32_t val, uint32_t addr);
+static void stm32_checksetup(void);
+#else
+# define stm32_getreg(addr) getreg32(addr)
+# define stm32_putreg(val,addr) putreg32(val,addr)
+# define stm32_checksetup()
+#endif
+
+/* Free buffer management */
+
+static void stm32_initbuffer(FAR struct stm32_ethmac_s *priv);
+static inline uint8_t *stm32_allocbuffer(FAR struct stm32_ethmac_s *priv);
+static inline void stm32_freebuffer(FAR struct stm32_ethmac_s *priv, uint8_t *buffer);
+static inline bool stm32_isfreebuffer(FAR struct stm32_ethmac_s *priv);
+
+/* Common TX logic */
+
+static int stm32_transmit(FAR struct stm32_ethmac_s *priv);
+static int stm32_uiptxpoll(struct uip_driver_s *dev);
+static void stm32_dopoll(FAR struct stm32_ethmac_s *priv);
+
+/* Interrupt handling */
+
+static void stm32_enableint(FAR struct stm32_ethmac_s *priv, uint32_t ierbit);
+static void stm32_disableint(FAR struct stm32_ethmac_s *priv, uint32_t ierbit);
+
+static void stm32_freesegment(FAR struct stm32_ethmac_s *priv,
+ FAR struct eth_rxdesc_s *rxfirst, int segments);
+static int stm32_recvframe(FAR struct stm32_ethmac_s *priv);
+static void stm32_receive(FAR struct stm32_ethmac_s *priv);
+static void stm32_freeframe(FAR struct stm32_ethmac_s *priv);
+static void stm32_txdone(FAR struct stm32_ethmac_s *priv);
+static int stm32_interrupt(int irq, FAR void *context);
+
+/* Watchdog timer expirations */
+
+static void stm32_polltimer(int argc, uint32_t arg, ...);
+static void stm32_txtimeout(int argc, uint32_t arg, ...);
+
+/* NuttX callback functions */
+
+static int stm32_ifup(struct uip_driver_s *dev);
+static int stm32_ifdown(struct uip_driver_s *dev);
+static int stm32_txavail(struct uip_driver_s *dev);
+#ifdef CONFIG_NET_IGMP
+static int stm32_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac);
+static int stm32_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac);
+#endif
+
+/* Descriptor Initialization */
+
+static void stm32_txdescinit(FAR struct stm32_ethmac_s *priv);
+static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv);
+
+/* PHY Initialization */
+
+static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value);
+static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value);
+static int stm32_phyinit(FAR struct stm32_ethmac_s *priv);
+
+/* MAC/DMA Initialization */
+
+static inline void stm32_ethgpioconfig(FAR struct stm32_ethmac_s *priv);
+static void stm32_ethreset(FAR struct stm32_ethmac_s *priv);
+static int stm32_macconfig(FAR struct stm32_ethmac_s *priv);
+static void stm32_macaddress(FAR struct stm32_ethmac_s *priv);
+static int stm32_macenable(FAR struct stm32_ethmac_s *priv);
+static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_getreg
+ *
+ * Description:
+ * This function may to used to intercept an monitor all register accesses.
+ * Clearly this is nothing you would want to do unless you are debugging
+ * this driver.
+ *
+ * Input Parameters:
+ * addr - The register address to read
+ *
+ * Returned Value:
+ * The value read from the register
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint32_t stm32_getreg(uint32_t addr)
+{
+ static uint32_t prevaddr = 0;
+ static uint32_t preval = 0;
+ static uint32_t count = 0;
+
+ /* Read the value from the register */
+
+ uint32_t val = getreg32(addr);
+
+ /* Is this the same value that we read from the same register last time?
+ * Are we polling the register? If so, suppress some of the output.
+ */
+
+ if (addr == prevaddr && val == preval)
+ {
+ if (count == 0xffffffff || ++count > 3)
+ {
+ if (count == 4)
+ {
+ lldbg("...\n");
+ }
+ return val;
+ }
+ }
+
+ /* No this is a new address or value */
+
+ else
+ {
+ /* Did we print "..." for the previous value? */
+
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
+
+ lldbg("[repeats %d more times]\n", count-3);
+ }
+
+ /* Save the new address, value, and count */
+
+ prevaddr = addr;
+ preval = val;
+ count = 1;
+ }
+
+ /* Show the register value read */
+
+ lldbg("%08x->%08x\n", addr, val);
+ return val;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_putreg
+ *
+ * Description:
+ * This function may to used to intercept an monitor all register accesses.
+ * Clearly this is nothing you would want to do unless you are debugging
+ * this driver.
+ *
+ * Input Parameters:
+ * val - The value to write to the register
+ * addr - The register address to read
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG)
+static void stm32_putreg(uint32_t val, uint32_t addr)
+{
+ /* Show the register value being written */
+
+ lldbg("%08x<-%08x\n", addr, val);
+
+ /* Write the value */
+
+ putreg32(val, addr);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_checksetup
+ *
+ * Description:
+ * Show the state of critical configuration registers.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG)
+static void stm32_checksetup(void)
+{
+}
+#endif
+
+/****************************************************************************
+ * Function: stm32_initbuffer
+ *
+ * Description:
+ * Initialize the free buffer list.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Called during early driver initialization before Ethernet interrupts
+ * are enabled.
+ *
+ ****************************************************************************/
+
+static void stm32_initbuffer(FAR struct stm32_ethmac_s *priv)
+{
+ uint8_t *buffer;
+ int i;
+
+ /* Initialize the head of the free buffer list */
+
+ sq_init(&priv->freeb);
+
+ /* Add all of the pre-allocated buffers to the free buffer list */
+
+ for (i = 0, buffer = priv->alloc;
+ i < STM32_ETH_NFREEBUFFERS;
+ i++, buffer += CONFIG_STM32_ETH_BUFSIZE)
+ {
+ sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb);
+ }
+}
+
+/****************************************************************************
+ * Function: stm32_allocbuffer
+ *
+ * Description:
+ * Allocate one buffer from the free buffer list.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * Pointer to the allocated buffer on success; NULL on failure
+ *
+ * Assumptions:
+ * May or may not be called from an interrupt handler. In either case,
+ * global interrupts are disabled, either explicitly or indirectly through
+ * interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static inline uint8_t *stm32_allocbuffer(FAR struct stm32_ethmac_s *priv)
+{
+ /* Allocate a buffer by returning the head of the free buffer list */
+
+ return (uint8_t *)sq_remfirst(&priv->freeb);
+}
+
+/****************************************************************************
+ * Function: stm32_freebuffer
+ *
+ * Description:
+ * Return a buffer to the free buffer list.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ * buffer - A pointer to the buffer to be freed
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * May or may not be called from an interrupt handler. In either case,
+ * global interrupts are disabled, either explicitly or indirectly through
+ * interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static inline void stm32_freebuffer(FAR struct stm32_ethmac_s *priv, uint8_t *buffer)
+{
+ /* Free the buffer by adding it to to the end of the free buffer list */
+
+ sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb);
+}
+
+/****************************************************************************
+ * Function: stm32_isfreebuffer
+ *
+ * Description:
+ * Return TRUE if the free buffer list is not empty.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * True if there are one or more buffers in the free buffer list;
+ * false if the free buffer list is empty
+ *
+ * Assumptions:
+ * None.
+ *
+ ****************************************************************************/
+
+static inline bool stm32_isfreebuffer(FAR struct stm32_ethmac_s *priv)
+{
+ /* Return TRUE if the free buffer list is not empty */
+
+ return !sq_empty(&priv->freeb);
+}
+
+/****************************************************************************
+ * Function: stm32_transmit
+ *
+ * Description:
+ * Start hardware transmission. Called either from the txdone interrupt
+ * handling or from watchdog based polling.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * OK on success; a negated errno on failure
+ *
+ * Assumptions:
+ * May or may not be called from an interrupt handler. In either case,
+ * global interrupts are disabled, either explicitly or indirectly through
+ * interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static int stm32_transmit(FAR struct stm32_ethmac_s *priv)
+{
+ struct eth_txdesc_s *txdesc;
+ struct eth_txdesc_s *txfirst;
+
+ /* The internal (optimal) uIP buffer size may be configured to be larger
+ * than the Ethernet buffer size.
+ */
+
+#if OPTIMAL_ETH_BUFSIZE > CONFIG_STM32_ETH_BUFSIZE
+ uint8_t *buffer;
+ int bufcount;
+ int lastsize;
+ int i;
+#endif
+
+ /* Verify that the hardware is ready to send another packet. If we get
+ * here, then we are committed to sending a packet; Higher level logic
+ * must have assured that there is no transmission in progress.
+ */
+
+ txdesc = priv->txhead;
+ txfirst = txdesc;
+
+ nllvdbg("d_len: %d d_buf: %p txhead: %p tdes0: %08x\n",
+ priv->dev.d_len, priv->dev.d_buf, txdesc, txdesc->tdes0);
+
+ DEBUGASSERT(txdesc && (txdesc->tdes0 & ETH_TDES0_OWN) == 0);
+
+ /* Is the size to be sent greater than the size of the Ethernet buffer? */
+
+ DEBUGASSERT(priv->dev.d_len > 0 && priv->dev.d_buf != NULL);
+
+#if OPTIMAL_ETH_BUFSIZE > CONFIG_STM32_ETH_BUFSIZE
+ if (priv->dev.d_len > CONFIG_STM32_ETH_BUFSIZE)
+ {
+ /* Yes... how many buffers will be need to send the packet? */
+
+ bufcount = (priv->dev.d_len + (CONFIG_STM32_ETH_BUFSIZE-1)) / CONFIG_STM32_ETH_BUFSIZE;
+ lastsize = priv->dev.d_len - (bufcount - 1) * CONFIG_STM32_ETH_BUFSIZE;
+
+ nllvdbg("bufcount: %d lastsize: %d\n", bufcount, lastsize);
+
+ /* Set the first segment bit in the first TX descriptor */
+
+ txdesc->tdes0 |= ETH_TDES0_FS;
+
+ /* Set up all but the last TX descriptor */
+
+ buffer = priv->dev.d_buf;
+
+ for (i = 0; i < bufcount; i++)
+ {
+ /* This could be a normal event but the design does not handle it */
+
+ DEBUGASSERT((txdesc->tdes0 & ETH_TDES0_OWN) == 0);
+
+ /* Set the Buffer1 address pointer */
+
+ txdesc->tdes2 = (uint32_t)buffer;
+
+ /* Set the buffer size in all TX descriptors */
+
+ if (i == (bufcount-1))
+ {
+ /* This is the last segment. Set the last segment bit in the
+ * last TX descriptor and ask for an interrupt when this
+ * segment transfer completes.
+ */
+
+ txdesc->tdes0 |= (ETH_TDES0_LS | ETH_TDES0_IC);
+
+ /* This segement is, most likely, of fractional buffersize */
+
+ txdesc->tdes1 = lastsize;
+ buffer += lastsize;
+ }
+ else
+ {
+ /* This is not the last segment. We don't want an interrupt
+ * when this segment transfer completes.
+ */
+
+ txdesc->tdes0 &= ~ETH_TDES0_IC;
+
+ /* The size of the transfer is the whole buffer */
+
+ txdesc->tdes1 = CONFIG_STM32_ETH_BUFSIZE;
+ buffer += CONFIG_STM32_ETH_BUFSIZE;
+ }
+
+ /* Give the descriptor to DMA */
+
+ txdesc->tdes0 |= ETH_TDES0_OWN;
+ txdesc = (struct eth_txdesc_s *)txdesc->tdes3;
+ }
+ }
+ else
+#endif
+ {
+ /* The single descriptor is both the first and last segment. And we do
+ * want an interrupt when the transfer completes.
+ */
+
+ txdesc->tdes0 |= (ETH_TDES0_FS | ETH_TDES0_LS | ETH_TDES0_IC);
+
+ /* Set frame size */
+
+ DEBUGASSERT(priv->dev.d_len <= CONFIG_NET_BUFSIZE);
+ txdesc->tdes1 = priv->dev.d_len;
+
+ /* Set the Buffer1 address pointer */
+
+ txdesc->tdes2 = (uint32_t)priv->dev.d_buf;
+
+ /* Set OWN bit of the TX descriptor tdes0. This gives the buffer to
+ * Ethernet DMA
+ */
+
+ txdesc->tdes0 |= ETH_TDES0_OWN;
+
+ /* Point to the next available TX descriptor */
+
+ txdesc = (struct eth_txdesc_s *)txdesc->tdes3;
+ }
+
+ /* Remember where we left off in the TX descriptor chain */
+
+ priv->txhead = txdesc;
+
+ /* Detach the buffer from priv->dev structure. That buffer is now
+ * "in-flight".
+ */
+
+ priv->dev.d_buf = NULL;
+ priv->dev.d_len = 0;
+
+ /* If there is no other TX buffer, in flight, then remember the location
+ * of the TX descriptor. This is the location to check for TX done events.
+ */
+
+ if (!priv->txtail)
+ {
+ DEBUGASSERT(priv->inflight == 0);
+ priv->txtail = txfirst;
+ }
+
+ /* Increment the number of TX transfer in-flight */
+
+ priv->inflight++;
+
+ nllvdbg("txhead: %p txtail: %p inflight: %d\n",
+ priv->txhead, priv->txtail, priv->inflight);
+
+ /* If all TX descriptors are in-flight, then we have to disable receive interrupts
+ * too. This is because receive events can trigger more un-stoppable transmit
+ * events.
+ */
+
+ if (priv->inflight >= CONFIG_STM32_ETH_NTXDESC)
+ {
+ stm32_disableint(priv, ETH_DMAINT_RI);
+ }
+
+ /* Check if the TX Buffer unavailable flag is set */
+
+ if ((stm32_getreg(STM32_ETH_DMASR) & ETH_DMAINT_TBUI) != 0)
+ {
+ /* Clear TX Buffer unavailable flag */
+
+ stm32_putreg(ETH_DMAINT_TBUI, STM32_ETH_DMASR);
+
+ /* Resume DMA transmission */
+
+ stm32_putreg(0, STM32_ETH_DMATPDR);
+ }
+
+ /* Enable TX interrupts */
+
+ stm32_enableint(priv, ETH_DMAINT_TI);
+
+ /* Setup the TX timeout watchdog (perhaps restarting the timer) */
+
+ (void)wd_start(priv->txtimeout, STM32_TXTIMEOUT, stm32_txtimeout, 1, (uint32_t)priv);
+ return OK;
+}
+
+/****************************************************************************
+ * Function: stm32_uiptxpoll
+ *
+ * Description:
+ * The transmitter is available, check if uIP has any outgoing packets ready
+ * to send. This is a callback from uip_poll(). uip_poll() may be called:
+ *
+ * 1. When the preceding TX packet send is complete,
+ * 2. When the preceding TX packet send timesout and the interface is reset
+ * 3. During normal TX polling
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ * OK on success; a negated errno on failure
+ *
+ * Assumptions:
+ * May or may not be called from an interrupt handler. In either case,
+ * global interrupts are disabled, either explicitly or indirectly through
+ * interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static int stm32_uiptxpoll(struct uip_driver_s *dev)
+{
+ FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
+
+ DEBUGASSERT(priv->dev.d_buf != NULL);
+
+ /* If the polling resulted in data that should be sent out on the network,
+ * the field d_len is set to a value > 0.
+ */
+
+ if (priv->dev.d_len > 0)
+ {
+ /* Send the packet */
+
+ uip_arp_out(&priv->dev);
+ stm32_transmit(priv);
+ DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL);
+
+ /* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We
+ * cannot perform the TX poll if we are unable to accept another packet for
+ * transmission.
+ *
+ * In a race condition, ETH_TDES0_OWN may be cleared BUT still not available
+ * because stm32_freeframe() has not yet run. If stm32_freeframe() has run,
+ * the buffer1 pointer (tdes2) will be nullified (and inflight should be <
+ * CONFIG_STM32_ETH_NTXDESC).
+ */
+
+ if ((priv->txhead->tdes0 & ETH_TDES0_OWN) != 0 ||
+ priv->txhead->tdes2 != 0)
+ {
+ /* We have to terminate the poll if we have no more descriptors
+ * available for another transfer.
+ */
+
+ return -EBUSY;
+ }
+
+ /* We have the descriptor, we can continue the poll. Allocate a new
+ * buffer for the poll.
+ */
+
+ dev->d_buf = stm32_allocbuffer(priv);
+
+ /* We can't continue the poll if we have no buffers */
+
+ if (dev->d_buf == NULL)
+ {
+ /* Terminate the poll. */
+
+ return -ENOMEM;
+ }
+ }
+
+ /* If zero is returned, the polling will continue until all connections have
+ * been examined.
+ */
+
+ return 0;
+}
+
+/****************************************************************************
+ * Function: stm32_dopoll
+ *
+ * Description:
+ * The function is called when a frame is received using the DMA receive
+ * interrupt. It scans the RX descriptors to the the received frame.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static void stm32_dopoll(FAR struct stm32_ethmac_s *priv)
+{
+ FAR struct uip_driver_s *dev = &priv->dev;
+
+ /* Check if the next TX descriptor is owned by the Ethernet DMA or
+ * CPU. We cannot perform the TX poll if we are unable to accept
+ * another packet for transmission.
+ *
+ * In a race condition, ETH_TDES0_OWN may be cleared BUT still not available
+ * because stm32_freeframe() has not yet run. If stm32_freeframe() has run,
+ * the buffer1 pointer (tdes2) will be nullified (and inflight should be <
+ * CONFIG_STM32_ETH_NTXDESC).
+ */
+
+ if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 &&
+ priv->txhead->tdes2 == 0)
+ {
+ /* If we have the descriptor, then poll uIP for new XMIT data.
+ * Allocate a buffer for the poll.
+ */
+
+ DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL);
+ dev->d_buf = stm32_allocbuffer(priv);
+
+ /* We can't poll if we have no buffers */
+
+ if (dev->d_buf)
+ {
+ (void)uip_poll(dev, stm32_uiptxpoll);
+
+ /* We will, most likely end up with a buffer to be freed. But it
+ * might not be the same one that we allocated above.
+ */
+
+ if (dev->d_buf)
+ {
+ DEBUGASSERT(dev->d_len == 0);
+ stm32_freebuffer(priv, dev->d_buf);
+ dev->d_buf = NULL;
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Function: stm32_enableint
+ *
+ * Description:
+ * Enable a "normal" interrupt
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static void stm32_enableint(FAR struct stm32_ethmac_s *priv, uint32_t ierbit)
+{
+ uint32_t regval;
+
+ /* Enable the specified "normal" interrupt */
+
+ regval = stm32_getreg(STM32_ETH_DMAIER);
+ regval |= (ETH_DMAINT_NIS | ierbit);
+ stm32_putreg(regval, STM32_ETH_DMAIER);
+}
+
+/****************************************************************************
+ * Function: stm32_disableint
+ *
+ * Description:
+ * Disable a normal interrupt.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static void stm32_disableint(FAR struct stm32_ethmac_s *priv, uint32_t ierbit)
+{
+ uint32_t regval;
+
+ /* Disable the "normal" interrupt */
+
+ regval = stm32_getreg(STM32_ETH_DMAIER);
+ regval &= ~ierbit;
+
+ /* Are all "normal" interrupts now disabled? */
+
+ if ((regval & ETH_DMAINT_NORMAL) == 0)
+ {
+ /* Yes.. disable normal interrupts */
+
+ regval &= ~ETH_DMAINT_NIS;
+ }
+
+ stm32_putreg(regval, STM32_ETH_DMAIER);
+}
+
+/****************************************************************************
+ * Function: stm32_freesegment
+ *
+ * Description:
+ * The function is called when a frame is received using the DMA receive
+ * interrupt. It scans the RX descriptors to the the received frame.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static void stm32_freesegment(FAR struct stm32_ethmac_s *priv,
+ FAR struct eth_rxdesc_s *rxfirst, int segments)
+{
+ struct eth_rxdesc_s *rxdesc;
+ int i;
+
+ nllvdbg("rxfirst: %p segments: %d\n", rxfirst, segments);
+
+ /* Set OWN bit in RX descriptors. This gives the buffers back to DMA */
+
+ rxdesc = rxfirst;
+ for (i = 0; i < segments; i++)
+ {
+ rxdesc->rdes0 = ETH_RDES0_OWN;
+ rxdesc = (struct eth_rxdesc_s *)rxdesc->rdes3;
+ }
+
+ /* Reset the segment managment logic */
+
+ priv->rxcurr = NULL;
+ priv->segments = 0;
+
+ /* Check if the RX Buffer unavailable flag is set */
+
+ if ((stm32_getreg(STM32_ETH_DMASR) & ETH_DMAINT_RBUI) != 0)
+ {
+ /* Clear RBUS Ethernet DMA flag */
+
+ stm32_putreg(ETH_DMAINT_RBUI, STM32_ETH_DMASR);
+
+ /* Resume DMA reception */
+
+ stm32_putreg(0, STM32_ETH_DMARPDR);
+ }
+}
+
+/****************************************************************************
+ * Function: stm32_recvframe
+ *
+ * Description:
+ * The function is called when a frame is received using the DMA receive
+ * interrupt. It scans the RX descriptors of the received frame.
+ *
+ * NOTE: This function will silently discard any packets containing errors.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * OK if a packet was successfully returned; -EAGAIN if there are no
+ * further packets available
+ *
+ * Assumptions:
+ * Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
+{
+ struct eth_rxdesc_s *rxdesc;
+ struct eth_rxdesc_s *rxcurr;
+ uint8_t *buffer;
+ int i;
+
+ nllvdbg("rxhead: %p rxcurr: %p segments: %d\n",
+ priv->rxhead, priv->rxcurr, priv->segments);
+
+ /* Check if there are free buffers. We cannot receive new frames in this
+ * design unless there is at least one free buffer.
+ */
+
+ if (!stm32_isfreebuffer(priv))
+ {
+ nlldbg("No free buffers\n");
+ return -ENOMEM;
+ }
+
+ /* Scan descriptors owned by the CPU. Scan until:
+ *
+ * 1) We find a descriptor still owned by the DMA,
+ * 2) We have examined all of the RX descriptors, or
+ * 3) All of the TX descriptors are in flight.
+ *
+ * This last case is obscure. It is due to that fact that each packet
+ * that we receive can generate an unstoppable transmisson. So we have
+ * to stop receiving when we can not longer transmit. In this case, the
+ * transmit logic should also have disabled further RX interrupts.
+ */
+
+ rxdesc = priv->rxhead;
+ for (i = 0;
+ (rxdesc->rdes0 & ETH_RDES0_OWN) == 0 &&
+ i < CONFIG_STM32_ETH_NRXDESC &&
+ priv->inflight < CONFIG_STM32_ETH_NTXDESC;
+ i++)
+ {
+ /* Check if this is the first segment in the frame */
+
+ if ((rxdesc->rdes0 & ETH_RDES0_FS) != 0 &&
+ (rxdesc->rdes0 & ETH_RDES0_LS) == 0)
+ {
+ priv->rxcurr = rxdesc;
+ priv->segments = 1;
+ }
+
+ /* Check if this is an intermediate segment in the frame */
+
+ else if (((rxdesc->rdes0 & ETH_RDES0_LS) == 0)&&
+ ((rxdesc->rdes0 & ETH_RDES0_FS) == 0))
+ {
+ priv->segments++;
+ }
+
+ /* Otherwise, it is the last segment in the frame */
+
+ else
+ {
+ priv->segments++;
+
+ nllvdbg("rxhead: %p rxcurr: %p segments: %d\n",
+ priv->rxhead, priv->rxcurr, priv->segments);
+
+ /* Check if the there is only one segment in the frame */
+
+ if (priv->segments == 1)
+ {
+ rxcurr = rxdesc;
+ }
+ else
+ {
+ rxcurr = priv->rxcurr;
+ }
+
+ /* Check if any errors are reported in the frame */
+
+ if ((rxdesc->rdes0 & ETH_RDES0_ES) == 0)
+ {
+ struct uip_driver_s *dev = &priv->dev;
+
+ /* Get the Frame Length of the received packet: substruct 4
+ * bytes of the CRC
+ */
+
+ dev->d_len = ((rxdesc->rdes0 & ETH_RDES0_FL_MASK) >> ETH_RDES0_FL_SHIFT) - 4;
+
+ /* Get a buffer from the free list. We don't even check if
+ * this is successful because we already assure the the free
+ * list is not empty above.
+ */
+
+ buffer = stm32_allocbuffer(priv);
+
+ /* Take the buffer from the RX descriptor of the first free
+ * segment, put it into the uIP device structure, then replace
+ * the buffer in the RX descriptor with the newly allocated
+ * buffer.
+ */
+
+ DEBUGASSERT(dev->d_buf == NULL);
+ dev->d_buf = (uint8_t*)rxcurr->rdes2;
+ rxcurr->rdes2 = (uint32_t)buffer;
+
+ /* Return success, remebering where we should re-start scanning
+ * and resetting the segment scanning logic
+ */
+
+ priv->rxhead = (struct eth_rxdesc_s*)rxdesc->rdes3;
+ stm32_freesegment(priv, rxcurr, priv->segments);
+
+ nllvdbg("rxhead: %p d_buf: %p d_len: %d\n",
+ priv->rxhead, dev->d_buf, dev->d_len);
+
+ return OK;
+ }
+ else
+ {
+ /* Drop the frame that contains the errors, reset the segment
+ * scanning logic, and continue scanning with the next frame.
+ */
+
+ nlldbg("DROPPED: RX descriptor errors: %08x\n", rxdesc->rdes0);
+ stm32_freesegment(priv, rxcurr, priv->segments);
+ }
+ }
+
+ /* Try the next descriptor */
+
+ rxdesc = (struct eth_rxdesc_s*)rxdesc->rdes3;
+ }
+
+ /* We get here after all of the descriptors have been scanned or when rxdesc points
+ * to the first descriptor owned by the DMA. Remember where we left off.
+ */
+
+ priv->rxhead = rxdesc;
+
+ nllvdbg("rxhead: %p rxcurr: %p segments: %d\n",
+ priv->rxhead, priv->rxcurr, priv->segments);
+
+ return -EAGAIN;
+}
+
+/****************************************************************************
+ * Function: stm32_receive
+ *
+ * Description:
+ * An interrupt was received indicating the availability of a new RX packet
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static void stm32_receive(FAR struct stm32_ethmac_s *priv)
+{
+ struct uip_driver_s *dev = &priv->dev;
+
+ /* Loop while while stm32_recvframe() successfully retrieves valid
+ * Ethernet frames.
+ */
+
+ while (stm32_recvframe(priv) == OK)
+ {
+ /* Check if the packet is a valid size for the uIP buffer configuration
+ * (this should not happen)
+ */
+
+ if (dev->d_len > CONFIG_NET_BUFSIZE)
+ {
+ nlldbg("DROPPED: Too big: %d\n", dev->d_len);
+ }
+
+ /* We only accept IP packets of the configured type and ARP packets */
+
+#ifdef CONFIG_NET_IPv6
+ else if (BUF->type == HTONS(UIP_ETHTYPE_IP6))
+#else
+ else if (BUF->type == HTONS(UIP_ETHTYPE_IP))
+#endif
+ {
+ nllvdbg("IP frame\n");
+
+ /* Handle ARP on input then give the IP packet to uIP */
+
+ uip_arp_ipin(&priv->dev);
+ uip_input(&priv->dev);
+
+ /* If the above function invocation resulted in data that should be
+ * sent out on the network, the field d_len will set to a value > 0.
+ */
+
+ if (priv->dev.d_len > 0)
+ {
+ uip_arp_out(&priv->dev);
+ stm32_transmit(priv);
+ }
+ }
+ else if (BUF->type == htons(UIP_ETHTYPE_ARP))
+ {
+ nllvdbg("ARP frame\n");
+
+ /* Handle ARP packet */
+
+ uip_arp_arpin(&priv->dev);
+
+ /* If the above function invocation resulted in data that should be
+ * sent out on the network, the field d_len will set to a value > 0.
+ */
+
+ if (priv->dev.d_len > 0)
+ {
+ stm32_transmit(priv);
+ }
+ }
+ else
+ {
+ nlldbg("DROPPED: Unknown type: %04x\n", BUF->type);
+ }
+
+ /* We are finished with the RX buffer. NOTE: If the buffer is
+ * re-used for transmission, the dev->d_buf field will have been
+ * nullified.
+ */
+
+ if (dev->d_buf)
+ {
+ /* Free the receive packet buffer */
+
+ stm32_freebuffer(priv, dev->d_buf);
+ dev->d_buf = NULL;
+ }
+ }
+}
+
+/****************************************************************************
+ * Function: stm32_freeframe
+ *
+ * Description:
+ * Scans the TX descriptors and frees the buffers of completed TX transfers.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None.
+ *
+ * Assumptions:
+ * Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static void stm32_freeframe(FAR struct stm32_ethmac_s *priv)
+{
+ struct eth_txdesc_s *txdesc;
+ int i;
+
+ nllvdbg("txhead: %p txtail: %p inflight: %d\n",
+ priv->txhead, priv->txtail, priv->inflight);
+
+ /* Scan for "in-flight" descriptors owned by the CPU */
+
+ txdesc = priv->txtail;
+ if (txdesc)
+ {
+ DEBUGASSERT(priv->inflight > 0);
+
+ for (i = 0; (txdesc->tdes0 & ETH_TDES0_OWN) == 0; i++)
+ {
+ /* There should be a buffer assigned to all in-flight
+ * TX descriptors.
+ */
+
+ nllvdbg("txtail: %p tdes0: %08x tdes2: %08x tdes3: %08x\n",
+ txdesc, txdesc->tdes0, txdesc->tdes2, txdesc->tdes3);
+
+ DEBUGASSERT(txdesc->tdes2 != 0);
+
+ /* Check if this is the first segment of a TX frame. */
+
+ if ((txdesc->tdes0 & ETH_TDES0_FS) != 0)
+ {
+ /* Yes.. Free the buffer */
+
+ stm32_freebuffer(priv, (uint8_t*)txdesc->tdes2);
+ }
+
+ /* In any event, make sure that TDES2 is nullified. */
+
+ txdesc->tdes2 = 0;
+
+ /* Check if this is the last segement of a TX frame */
+
+ if ((txdesc->tdes0 & ETH_TDES0_FS) != 0)
+ {
+ /* Yes.. Decrement the number of frames "in-flight". */
+
+ priv->inflight--;
+
+ /* If all of the TX descriptors were in-flight, then RX interrupts
+ * may have been disabled... we can re-enable them now.
+ */
+
+ stm32_enableint(priv, ETH_DMAINT_RI);
+
+ /* If there are no more frames in-flight, then bail. */
+
+ if (priv->inflight <= 0)
+ {
+ priv->txtail = NULL;
+ priv->inflight = 0;
+ return;
+ }
+ }
+
+ /* Try the next descriptor in the TX chain */
+
+ txdesc = (struct eth_txdesc_s*)txdesc->tdes3;
+ }
+
+ /* We get here if (1) there are still frames "in-flight". Remember
+ * where we left off.
+ */
+
+ priv->txtail = txdesc;
+
+ nllvdbg("txhead: %p txtail: %p inflight: %d\n",
+ priv->txhead, priv->txtail, priv->inflight);
+ }
+}
+
+/****************************************************************************
+ * Function: stm32_txdone
+ *
+ * Description:
+ * An interrupt was received indicating that the last TX packet(s) is done
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Global interrupts are disabled by the watchdog logic.
+ *
+ ****************************************************************************/
+
+static void stm32_txdone(FAR struct stm32_ethmac_s *priv)
+{
+ DEBUGASSERT(priv->txtail != NULL);
+
+ /* Scan the TX desciptor change, returning buffers to free list */
+
+ stm32_freeframe(priv);
+
+ /* If no further xmits are pending, then cancel the TX timeout */
+
+ if (priv->inflight <= 0)
+ {
+ wd_cancel(priv->txtimeout);
+
+ /* And disable further TX interrupts. */
+
+ stm32_disableint(priv, ETH_DMAINT_TI);
+ }
+
+ /* Then poll uIP for new XMIT data */
+
+ stm32_dopoll(priv);
+}
+
+/****************************************************************************
+ * Function: stm32_interrupt
+ *
+ * Description:
+ * Hardware interrupt handler
+ *
+ * Parameters:
+ * irq - Number of the IRQ that generated the interrupt
+ * context - Interrupt register state save info (architecture-specific)
+ *
+ * Returned Value:
+ * OK on success
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32_interrupt(int irq, FAR void *context)
+{
+ register FAR struct stm32_ethmac_s *priv = &g_stm32ethmac[0];
+ uint32_t dmasr;
+
+ /* Get the DMA interrupt status bits (no MAC interrupts are expected) */
+
+ dmasr = stm32_getreg(STM32_ETH_DMASR);
+
+ /* Mask only enabled interrupts. This depends on the fact that the interrupt
+ * related bits (0-16) correspond in these two registers.
+ */
+
+ dmasr &= stm32_getreg(STM32_ETH_DMAIER);
+
+ /* Check if there are pending "normal" interrupts */
+
+ if ((dmasr & ETH_DMAINT_NIS) != 0)
+ {
+ /* Yes.. Check if we received an incoming packet, if so, call
+ * stm32_receive()
+ */
+
+ if ((dmasr & ETH_DMAINT_RI) != 0)
+ {
+ /* Clear the pending receive interrupt */
+
+ stm32_putreg(ETH_DMAINT_RI, STM32_ETH_DMASR);
+
+ /* Handle the received package */
+
+ stm32_receive(priv);
+ }
+
+ /* Check if a packet transmission just completed. If so, call
+ * stm32_txdone(). This may disable further TX interrupts if there
+ * are no pending tansmissions.
+ */
+
+ if ((dmasr & ETH_DMAINT_TI) != 0)
+ {
+ /* Clear the pending receive interrupt */
+
+ stm32_putreg(ETH_DMAINT_TI, STM32_ETH_DMASR);
+
+ /* Check if there are pending transmissions */
+
+ stm32_txdone(priv);
+ }
+
+ /* Clear the pending normal summary interrupt */
+
+ stm32_putreg(ETH_DMAINT_NIS, STM32_ETH_DMASR);
+ }
+
+ /* Handle error interrupt only if CONFIG_DEBUG_NET is eanbled */
+
+#ifdef CONFIG_DEBUG_NET
+
+ /* Check if there are pending "anormal" interrupts */
+
+ if ((dmasr & ETH_DMAINT_AIS) != 0)
+ {
+ /* Just let the user know what happened */
+
+ nlldbg("Abormal event(s): %08x\n", dmasr);
+
+ /* Clear all pending abnormal events */
+
+ stm32_putreg(ETH_DMAINT_ABNORMAL, STM32_ETH_DMASR);
+
+ /* Clear the pending abnormal summary interrupt */
+
+ stm32_putreg(ETH_DMAINT_AIS, STM32_ETH_DMASR);
+ }
+#endif
+ return OK;
+}
+
+/****************************************************************************
+ * Function: stm32_txtimeout
+ *
+ * Description:
+ * Our TX watchdog timed out. Called from the timer interrupt handler.
+ * The last TX never completed. Reset the hardware and start again.
+ *
+ * Parameters:
+ * argc - The number of available arguments
+ * arg - The first argument
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Global interrupts are disabled by the watchdog logic.
+ *
+ ****************************************************************************/
+
+static void stm32_txtimeout(int argc, uint32_t arg, ...)
+{
+ FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
+
+ nlldbg("Timeout!\n");
+
+ /* Then reset the hardware. Just take the interface down, then back
+ * up again.
+ */
+
+ stm32_ifdown(&priv->dev);
+ stm32_ifup(&priv->dev);
+
+ /* Then poll uIP for new XMIT data */
+
+ stm32_dopoll(priv);
+}
+
+/****************************************************************************
+ * Function: stm32_polltimer
+ *
+ * Description:
+ * Periodic timer handler. Called from the timer interrupt handler.
+ *
+ * Parameters:
+ * argc - The number of available arguments
+ * arg - The first argument
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Global interrupts are disabled by the watchdog logic.
+ *
+ ****************************************************************************/
+
+static void stm32_polltimer(int argc, uint32_t arg, ...)
+{
+ FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
+ FAR struct uip_driver_s *dev = &priv->dev;
+
+ /* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We
+ * cannot perform the timer poll if we are unable to accept another packet
+ * for transmission. Hmmm.. might be bug here. Does this mean if there is
+ * a transmit in progress, we will missing TCP time state updates?
+ *
+ * In a race condition, ETH_TDES0_OWN may be cleared BUT still not available
+ * because stm32_freeframe() has not yet run. If stm32_freeframe() has run,
+ * the buffer1 pointer (tdes2) will be nullified (and inflight should be <
+ * CONFIG_STM32_ETH_NTXDESC).
+ */
+
+ if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 &&
+ priv->txhead->tdes2 == 0)
+ {
+ /* If we have the descriptor, then perform the timer poll. Allocate a
+ * buffer for the poll.
+ */
+
+ DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL);
+ dev->d_buf = stm32_allocbuffer(priv);
+
+ /* We can't poll if we have no buffers */
+
+ if (dev->d_buf)
+ {
+ /* Update TCP timing states and poll uIP for new XMIT data.
+ */
+
+ (void)uip_timer(dev, stm32_uiptxpoll, STM32_POLLHSEC);
+
+ /* We will, most likely end up with a buffer to be freed. But it
+ * might not be the same one that we allocated above.
+ */
+
+ if (dev->d_buf)
+ {
+ DEBUGASSERT(dev->d_len == 0);
+ stm32_freebuffer(priv, dev->d_buf);
+ dev->d_buf = NULL;
+ }
+ }
+ }
+
+ /* Setup the watchdog poll timer again */
+
+ (void)wd_start(priv->txpoll, STM32_WDDELAY, stm32_polltimer, 1, arg);
+}
+
+/****************************************************************************
+ * Function: stm32_ifup
+ *
+ * Description:
+ * NuttX Callback: Bring up the Ethernet interface when an IP address is
+ * provided
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32_ifup(struct uip_driver_s *dev)
+{
+ FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
+ int ret;
+
+ ndbg("Bringing up: %d.%d.%d.%d\n",
+ dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff,
+ (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 );
+
+ /* Configure the Ethernet interface for DMA operation. */
+
+ ret = stm32_ethconfig(priv);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Set and activate a timer process */
+
+ (void)wd_start(priv->txpoll, STM32_WDDELAY, stm32_polltimer, 1, (uint32_t)priv);
+
+ /* Enable the Ethernet interrupt */
+
+ priv->ifup = true;
+ up_enable_irq(STM32_IRQ_ETH);
+
+ stm32_checksetup();
+ return OK;
+}
+
+/****************************************************************************
+ * Function: stm32_ifdown
+ *
+ * Description:
+ * NuttX Callback: Stop the interface.
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32_ifdown(struct uip_driver_s *dev)
+{
+ FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
+ irqstate_t flags;
+
+ ndbg("Taking the network down\n");
+
+ /* Disable the Ethernet interrupt */
+
+ flags = irqsave();
+ up_disable_irq(STM32_IRQ_ETH);
+
+ /* Cancel the TX poll timer and TX timeout timers */
+
+ wd_cancel(priv->txpoll);
+ wd_cancel(priv->txtimeout);
+
+ /* Put the EMAC in its reset, non-operational state. This should be
+ * a known configuration that will guarantee the stm32_ifup() always
+ * successfully brings the interface back up.
+ */
+
+ stm32_ethreset(priv);
+
+ /* Mark the device "down" */
+
+ priv->ifup = false;
+ irqrestore(flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Function: stm32_txavail
+ *
+ * Description:
+ * Driver callback invoked when new TX data is available. This is a
+ * stimulus perform an out-of-cycle poll and, thereby, reduce the TX
+ * latency.
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Called in normal user mode
+ *
+ ****************************************************************************/
+
+static int stm32_txavail(struct uip_driver_s *dev)
+{
+ FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
+ irqstate_t flags;
+
+ nllvdbg("ifup: %d\n", priv->ifup);
+
+ /* Disable interrupts because this function may be called from interrupt
+ * level processing.
+ */
+
+ flags = irqsave();
+
+ /* Ignore the notification if the interface is not yet up */
+
+ if (priv->ifup)
+ {
+ /* Poll uIP for new XMIT data */
+
+ stm32_dopoll(priv);
+ }
+
+ irqrestore(flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Function: stm32_addmac
+ *
+ * Description:
+ * NuttX Callback: Add the specified MAC address to the hardware multicast
+ * address filtering
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ * mac - The MAC address to be added
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_IGMP
+static int stm32_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac)
+{
+ FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
+
+ nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ /* Add the MAC address to the hardware multicast routing table */
+ /* Add the MAC address to the hardware multicast routing table */
+#error "Missing logic"
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Function: stm32_rmmac
+ *
+ * Description:
+ * NuttX Callback: Remove the specified MAC address from the hardware multicast
+ * address filtering
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ * mac - The MAC address to be removed
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_IGMP
+static int stm32_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac)
+{
+ FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
+
+ nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ /* Add the MAC address to the hardware multicast routing table */
+#error "Missing logic"
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Function: stm32_txdescinit
+ *
+ * Description:
+ * Initializes the DMA TX descriptors in chain mode.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void stm32_txdescinit(FAR struct stm32_ethmac_s *priv)
+{
+ struct eth_txdesc_s *txdesc;
+ int i;
+
+ /* priv->txhead will point to the first, available TX descriptor in the chain.
+ * Set the priv->txhead pointer to the first descriptor in the table.
+ */
+
+ priv->txhead = priv->txtable;
+
+ /* priv->txtail will point to the first segment of the oldest pending
+ * "in-flight" TX transfer. NULL means that there are no active TX
+ * transfers.
+ */
+
+ priv->txtail = NULL;
+ priv->inflight = 0;
+
+ /* Initialize each TX descriptor */
+
+ for (i = 0; i < CONFIG_STM32_ETH_NTXDESC; i++)
+ {
+ txdesc = &priv->txtable[i];
+
+ /* Set Second Address Chained bit */
+
+ txdesc->tdes0 = ETH_TDES0_TCH;
+
+#ifdef CHECKSUM_BY_HARDWARE
+ /* Enable the checksum insertion for the TX frames */
+
+ txdesc->tdes0 |= ETH_TDES0_CIC_ALL;
+#endif
+
+ /* Clear Buffer1 address pointer (buffers will be assigned as they
+ * are used)
+ */
+
+ txdesc->tdes2 = 0;
+
+ /* Initialize the next descriptor with the Next Descriptor Polling Enable */
+
+ if( i < (CONFIG_STM32_ETH_NTXDESC-1))
+ {
+ /* Set next descriptor address register with next descriptor base
+ * address
+ */
+
+ txdesc->tdes3 = (uint32_t)&priv->txtable[i+1];
+ }
+ else
+ {
+ /* For last descriptor, set next descriptor address register equal
+ * to the first descriptor base address
+ */
+
+ txdesc->tdes3 = (uint32_t)priv->txtable;
+ }
+ }
+
+ /* Set Transmit Desciptor List Address Register */
+
+ stm32_putreg((uint32_t)priv->txtable, STM32_ETH_DMATDLAR);
+}
+
+/****************************************************************************
+ * Function: stm32_rxdescinit
+ *
+ * Description:
+ * Initializes the DMA RX descriptors in chain mode.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv)
+{
+ struct eth_rxdesc_s *rxdesc;
+ int i;
+
+ /* priv->rxhead will point to the first, RX descriptor in the chain.
+ * This will be where we receive the first incomplete frame.
+ */
+
+ priv->rxhead = priv->rxtable;
+
+ /* If we accumulate the frame in segments, priv->rxcurr points to the
+ * RX descriptor of the first segment in the current TX frame.
+ */
+
+ priv->rxcurr = NULL;
+ priv->segments = 0;
+
+ /* Initialize each TX descriptor */
+
+ for (i = 0; i < CONFIG_STM32_ETH_NRXDESC; i++)
+ {
+ rxdesc = &priv->rxtable[i];
+
+ /* Set Own bit of the RX descriptor rdes0 */
+
+ rxdesc->rdes0 = ETH_RDES0_OWN;
+
+ /* Set Buffer1 size and Second Address Chained bit and enabled DMA
+ * RX desc receive interrupt
+ */
+
+ rxdesc->rdes1 = ETH_RDES1_RCH | (uint32_t)CONFIG_STM32_ETH_BUFSIZE;
+
+ /* Set Buffer1 address pointer */
+
+ rxdesc->rdes2 = (uint32_t)&priv->rxbuffer[i*CONFIG_STM32_ETH_BUFSIZE];
+
+ /* Initialize the next descriptor with the Next Descriptor Polling Enable */
+
+ if( i < (CONFIG_STM32_ETH_NRXDESC-1))
+ {
+ /* Set next descriptor address register with next descriptor base
+ * address
+ */
+
+ rxdesc->rdes3 = (uint32_t)&priv->rxtable[i+1];
+ }
+ else
+ {
+ /* For last descriptor, set next descriptor address register equal
+ * to the first descriptor base address
+ */
+
+ rxdesc->rdes3 = (uint32_t)priv->rxtable;
+ }
+ }
+
+ /* Set Receive Descriptor List Address Register */
+
+ stm32_putreg((uint32_t)priv->rxtable, STM32_ETH_DMARDLAR);
+}
+
+/****************************************************************************
+ * Function: stm32_phyread
+ *
+ * Description:
+ * Read a PHY register.
+ *
+ * Parameters:
+ * phydevaddr - The PHY device address
+ * phyregaddr - The PHY register address
+ * value - The location to return the 16-bit PHY register value.
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value)
+{
+ volatile uint32_t timeout;
+ uint32_t regval;
+
+ /* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */
+
+ regval = stm32_getreg(STM32_ETH_MACMIIAR);
+ regval &= ETH_MACMIIAR_CR_MASK;
+
+ /* Set the PHY device address, PHY register address, and set the buy bit.
+ * the ETH_MACMIIAR_MW is clear, indicating a read operation.
+ */
+
+ regval |= (((uint32_t)phydevaddr << ETH_MACMIIAR_PA_SHIFT) & ETH_MACMIIAR_PA_MASK);
+ regval |= (((uint32_t)phyregaddr << ETH_MACMIIAR_MR_SHIFT) & ETH_MACMIIAR_MR_MASK);
+ regval |= ETH_MACMIIAR_MB;
+
+ stm32_putreg(regval, STM32_ETH_MACMIIAR);
+
+ /* Wait for the transfer to complete */
+
+ for (timeout = 0; timeout < PHY_READ_TIMEOUT; timeout++)
+ {
+ if ((stm32_getreg(STM32_ETH_MACMIIAR) & ETH_MACMIIAR_MB) == 0)
+ {
+ *value = (uint16_t)stm32_getreg(STM32_ETH_MACMIIDR);
+ return OK;
+ }
+ }
+
+ ndbg("MII transfer timed out: phydevaddr: %04x phyregaddr: %04x\n",
+ phydevaddr, phyregaddr);
+
+ return -ETIMEDOUT;
+}
+
+/****************************************************************************
+ * Function: stm32_phywrite
+ *
+ * Description:
+ * Write to a PHY register.
+ *
+ * Parameters:
+ * phydevaddr - The PHY device address
+ * phyregaddr - The PHY register address
+ * value - The 16-bit value to write to the PHY register value.
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value)
+{
+ volatile uint32_t timeout;
+ uint32_t regval;
+
+ /* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */
+
+ regval = stm32_getreg(STM32_ETH_MACMIIAR);
+ regval &= ETH_MACMIIAR_CR_MASK;
+
+ /* Set the PHY device address, PHY register address, and set the busy bit.
+ * the ETH_MACMIIAR_MW is set, indicating a write operation.
+ */
+
+ regval |= (((uint32_t)phydevaddr << ETH_MACMIIAR_PA_SHIFT) & ETH_MACMIIAR_PA_MASK);
+ regval |= (((uint32_t)phyregaddr << ETH_MACMIIAR_MR_SHIFT) & ETH_MACMIIAR_MR_MASK);
+ regval |= (ETH_MACMIIAR_MB | ETH_MACMIIAR_MW);
+
+ /* Write the value into the MACIIDR register before setting the new MACMIIAR
+ * register value.
+ */
+
+ stm32_putreg(value, STM32_ETH_MACMIIDR);
+ stm32_putreg(regval, STM32_ETH_MACMIIAR);
+
+ /* Wait for the transfer to complete */
+
+ for (timeout = 0; timeout < PHY_WRITE_TIMEOUT; timeout++)
+ {
+ if ((stm32_getreg(STM32_ETH_MACMIIAR) & ETH_MACMIIAR_MB) == 0)
+ {
+ return OK;
+ }
+ }
+
+ ndbg("MII transfer timed out: phydevaddr: %04x phyregaddr: %04x value: %04x\n",
+ phydevaddr, phyregaddr, value);
+
+ return -ETIMEDOUT;
+}
+
+/****************************************************************************
+ * Function: stm32_phyinit
+ *
+ * Description:
+ * Configure the PHY and determine the link speed/duplex.
+ *
+ * Parameters:
+ * priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32_phyinit(FAR struct stm32_ethmac_s *priv)
+{
+ volatile uint32_t timeout;
+ uint32_t regval;
+ uint16_t phyval;
+ int ret;
+
+ /* Assume 10MBps and half duplex */
+
+ priv->mbps100 = 0;
+ priv->fduplex = 0;
+
+ /* Setup up PHY clocking by setting the SR field in the MACMIIAR register */
+
+ regval = stm32_getreg(STM32_ETH_MACMIIAR);
+ regval &= ~ETH_MACMIIAR_CR_MASK;
+ regval |= ETH_MACMIIAR_CR;
+ stm32_putreg(regval, STM32_ETH_MACMIIAR);
+
+ /* Put the PHY in reset mode */
+
+ ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, MII_MCR_RESET);
+ if (ret < 0)
+ {
+ ndbg("Failed to reset the PHY: %d\n", ret);
+ return ret;
+ }
+ up_mdelay(PHY_RESET_DELAY);
+
+ /* Perform auto-negotion if so configured */
+
+#ifdef CONFIG_STM32_AUTONEG
+ /* Wait for link status */
+
+ for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++)
+ {
+ ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_MSR, &phyval);
+ if (ret < 0)
+ {
+ ndbg("Failed to read the PHY MSR: %d\n", ret);
+ return ret;
+ }
+ else if ((phyval & MII_MSR_LINKSTATUS) != 0)
+ {
+ break;
+ }
+ }
+
+ if (timeout >= PHY_RETRY_TIMEOUT)
+ {
+ ndbg("Timed out waiting for link status\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Enable auto-gegotiation */
+
+ ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, MII_MCR_ANENABLE);
+ if (ret < 0)
+ {
+ ndbg("Failed to enable auto-negotiation: %d\n", ret);
+ return ret;
+ }
+
+ /* Wait until auto-negotiation completes */
+
+ for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++)
+ {
+ ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_MSR, &phyval);
+ if (ret < 0)
+ {
+ ndbg("Failed to read the PHY MSR: %d\n", ret);
+ return ret;
+ }
+ else if ((phyval & MII_MSR_ANEGCOMPLETE) != 0)
+ {
+ break;
+ }
+ }
+
+ if (timeout >= PHY_RETRY_TIMEOUT)
+ {
+ ndbg("Timed out waiting for auto-negotiation\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Read the result of the auto-negotiation from the PHY-specific register */
+
+ ret = stm32_phyread(CONFIG_STM32_PHYADDR, CONFIG_STM32_PHYSR, &phyval);
+ if (ret < 0)
+ {
+ ndbg("Failed to read PHY status register\n");
+ return ret;
+ }
+
+ /* Remember the selected speed and duplex modes */
+
+ if ((phyval & CONFIG_STM32_PHYSR_MODE) == CONFIG_STM32_PHYSR_FULLDUPLEX)
+ {
+ priv->fduplex = 1;
+ }
+
+ if ((phyval & CONFIG_STM32_PHYSR_SPEED) == CONFIG_STM32_PHYSR_100MBPS)
+ {
+ priv->mbps100 = 1;
+ }
+
+#else /* Auto-negotion not selected */
+
+ phyval = 0;
+#ifdef CONFIG_STM32_ETHFD
+ phyval |= MII_MCR_FULLDPLX;
+#endif
+#ifdef CONFIG_STM32_ETH100MBPS
+ phyval |= MII_MCR_SPEED100;
+#endif
+
+ ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, phyval);
+ if (ret < 0)
+ {
+ ndbg("Failed to write the PHY MCR: %d\n", ret);
+ return ret;
+ }
+ up_mdelay(PHY_CONFIG_DELAY);
+
+ /* Remember the selected speed and duplex modes */
+
+#ifdef CONFIG_STM32_ETHFD
+ priv->fduplex = 1;
+#endif
+#ifdef CONFIG_STM32_ETH100MBPS
+ priv->mbps100 = 1;
+#endif
+#endif
+
+ ndbg("Duplex: %s Speed: %d MBps\n",
+ priv->fduplex ? "FULL" : "HALF",
+ priv->mbps100 ? 100 : 10);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Function: stm32_ethgpioconfig
+ *
+ * Description:
+ * Configure GPIOs for the Ethernet interface.
+ *
+ * Parameters:
+ * priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ * None.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static inline void stm32_ethgpioconfig(FAR struct stm32_ethmac_s *priv)
+{
+ /* Configure GPIO pins to support Ethernet */
+
+#if defined(CONFIG_STM32_MII) || defined(CONFIG_STM32_RMII)
+
+ /* MDC and MDIO are common to both modes */
+
+ stm32_configgpio(GPIO_ETH_MDC);
+ stm32_configgpio(GPIO_ETH_MDIO);
+
+ /* Set up the MII interface */
+
+#if defined(CONFIG_STM32_MII)
+
+ /* Select the MII interface */
+
+ stm32_selectmii();
+
+ /* Provide clocking via MCO1 or MCO2:
+ *
+ * "MCO1 (microcontroller clock output), used to output HSI, LSE, HSE or PLL
+ * clock (through a configurable prescaler) on PA8 pin."
+ *
+ * "MCO2 (microcontroller clock output), used to output HSE, PLL, SYSCLK or
+ * PLLI2S clock (through a configurable prescaler) on PC9 pin."
+ */
+
+# if defined(CONFIG_STM32_MII_MCO1)
+ /* Configure MC01 to drive the PHY. Board logic must provide MC01 clocking
+ * info.
+ */
+
+ stm32_configgpio(GPIO_MCO1);
+ stm32_mco1config(BOARD_CFGR_MC01_SOURCE, BOARD_CFGR_MC01_DIVIDER);
+
+# elif defined(CONFIG_STM32_MII_MCO2)
+ /* Configure MC02 to drive the PHY. Board logic must provide MC02 clocking
+ * info.
+ */
+
+ stm32_configgpio(GPIO_MCO2);
+ stm32_mco2config(BOARD_CFGR_MC02_SOURCE, BOARD_CFGR_MC02_DIVIDER);
+# endif
+
+ /* MII interface pins (17):
+ *
+ * MII_TX_CLK, MII_TXD[3:0], MII_TX_EN, MII_RX_CLK, MII_RXD[3:0], MII_RX_ER,
+ * MII_RX_DV, MII_CRS, MII_COL, MDC, MDIO
+ */
+
+ stm32_configgpio(GPIO_ETH_MII_COL);
+ stm32_configgpio(GPIO_ETH_MII_CRS);
+ stm32_configgpio(GPIO_ETH_MII_RXD0);
+ stm32_configgpio(GPIO_ETH_MII_RXD1);
+ stm32_configgpio(GPIO_ETH_MII_RXD2);
+ stm32_configgpio(GPIO_ETH_MII_RXD3);
+ stm32_configgpio(GPIO_ETH_MII_RX_CLK);
+ stm32_configgpio(GPIO_ETH_MII_RX_DV);
+ stm32_configgpio(GPIO_ETH_MII_RX_ER);
+ stm32_configgpio(GPIO_ETH_MII_TXD0);
+ stm32_configgpio(GPIO_ETH_MII_TXD1);
+ stm32_configgpio(GPIO_ETH_MII_TXD2);
+ stm32_configgpio(GPIO_ETH_MII_TXD3);
+ stm32_configgpio(GPIO_ETH_MII_TX_CLK);
+ stm32_configgpio(GPIO_ETH_MII_TX_EN);
+
+ /* Set up the RMII interface. */
+
+#elif defined(CONFIG_STM32_RMII)
+
+ /* Select the RMII interface */
+
+ stm32_selectrmii();
+
+ /* RMII interface pins (7):
+ *
+ * RMII_TXD[1:0], RMII_TX_EN, RMII_RXD[1:0], RMII_CRS_DV, MDC, MDIO,
+ * RMII_REF_CLK
+ */
+
+ stm32_configgpio(GPIO_ETH_RMII_CRS_DV);
+ stm32_configgpio(GPIO_ETH_RMII_REF_CLK);
+ stm32_configgpio(GPIO_ETH_RMII_RXD0);
+ stm32_configgpio(GPIO_ETH_RMII_RXD1);
+ stm32_configgpio(GPIO_ETH_RMII_TXD0);
+ stm32_configgpio(GPIO_ETH_RMII_TXD1);
+ stm32_configgpio(GPIO_ETH_RMII_TX_CLK);
+ stm32_configgpio(GPIO_ETH_RMII_TX_EN);
+
+#endif
+#endif
+
+ /* Enable pulse-per-second (PPS) output signal */
+
+ stm32_configgpio(GPIO_ETH_PPS_OUT);
+}
+
+/****************************************************************************
+ * Function: stm32_ethreset
+ *
+ * Description:
+ * Reset the Ethernet block.
+ *
+ * Parameters:
+ * priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ * None.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void stm32_ethreset(FAR struct stm32_ethmac_s *priv)
+{
+ uint32_t regval;
+
+ /* Reset the Ethernet on the AHB1 bus */
+
+ regval = stm32_getreg(STM32_RCC_AHB1RSTR);
+ regval |= RCC_AHB1RSTR_ETHMACRST;
+ stm32_putreg(regval, STM32_RCC_AHB1RSTR);
+
+ regval &= ~RCC_AHB1RSTR_ETHMACRST;
+ stm32_putreg(regval, STM32_RCC_AHB1RSTR);
+
+ /* Perform a software reset by setting the SR bit in the DMABMR register.
+ * This Resets all MAC subsystem internal registers and logic. After this
+ * reset all the registers holds their reset values.
+ */
+
+ regval = stm32_getreg(STM32_ETH_DMABMR);
+ regval |= ETH_DMABMR_SR;
+ stm32_putreg(regval, STM32_ETH_DMABMR);
+
+ /* Wait for software reset to complete. The SR bit is cleared automatically
+ * after the reset operation has completed in all of the core clock domains.
+ */
+
+ while ((stm32_getreg(STM32_ETH_DMABMR) & ETH_DMABMR_SR) != 0);
+}
+
+/****************************************************************************
+ * Function: stm32_macconfig
+ *
+ * Description:
+ * Configure the Ethernet MAC for DMA operation.
+ *
+ * Parameters:
+ * priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32_macconfig(FAR struct stm32_ethmac_s *priv)
+{
+ uint32_t regval;
+
+ /* Set up the MACCR register */
+
+ regval = stm32_getreg(STM32_ETH_MACCR);
+ regval &= ~MACCR_CLEAR_BITS;
+ regval |= MACCR_SET_BITS;
+
+ if (priv->fduplex)
+ {
+ /* Set the DM bit for full duplex support */
+
+ regval |= ETH_MACCR_DM;
+ }
+
+ if (priv->mbps100)
+ {
+ /* Set the FES bit for 100Mbps fast ethernet support */
+
+ regval |= ETH_MACCR_FES;
+ }
+
+ stm32_putreg(regval, STM32_ETH_MACCR);
+
+ /* Set up the MACFFR register */
+
+ regval = stm32_getreg(STM32_ETH_MACFFR);
+ regval &= ~MACFFR_CLEAR_BITS;
+ regval |= MACFFR_SET_BITS;
+ stm32_putreg(regval, STM32_ETH_MACFFR);
+
+ /* Set up the MACHTHR and MACHTLR registers */
+
+ stm32_putreg(0, STM32_ETH_MACHTHR);
+ stm32_putreg(0, STM32_ETH_MACHTLR);
+
+ /* Setup up the MACFCR register */
+
+ regval = stm32_getreg(STM32_ETH_MACFCR);
+ regval &= ~MACFCR_CLEAR_MASK;
+ regval |= MACFCR_SET_MASK;
+ stm32_putreg(regval, STM32_ETH_MACFCR);
+
+ /* Setup up the MACVLANTR register */
+
+ stm32_putreg(0, STM32_ETH_MACVLANTR);
+
+ /* DMA Configuration */
+ /* Set up the DMAOMR register */
+
+ regval = stm32_getreg(STM32_ETH_DMAOMR);
+ regval &= ~DMAOMR_CLEAR_MASK;
+ regval |= DMAOMR_SET_MASK;
+ stm32_putreg(regval, STM32_ETH_DMAOMR);
+
+ /* Set up the DMABMR register */
+
+ regval = stm32_getreg(STM32_ETH_DMABMR);
+ regval &= ~DMABMR_CLEAR_MASK;
+ regval |= DMABMR_SET_MASK;
+ stm32_putreg(regval, STM32_ETH_DMABMR);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Function: stm32_macaddress
+ *
+ * Description:
+ * Configure the selected MAC address.
+ *
+ * Parameters:
+ * priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void stm32_macaddress(FAR struct stm32_ethmac_s *priv)
+{
+ FAR struct uip_driver_s *dev = &priv->dev;
+ uint32_t regval;
+
+ nllvdbg("%s MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->d_ifname,
+ dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1],
+ dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3],
+ dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5]);
+
+ /* Set the MAC address high register */
+
+ regval = ((uint32_t)dev->d_mac.ether_addr_octet[5] << 8) |
+ (uint32_t)dev->d_mac.ether_addr_octet[4];
+ stm32_putreg(regval, STM32_ETH_MACA0HR);
+
+ /* Set the MAC address low register */
+
+ regval = ((uint32_t)dev->d_mac.ether_addr_octet[3] << 24) |
+ ((uint32_t)dev->d_mac.ether_addr_octet[2] << 16) |
+ ((uint32_t)dev->d_mac.ether_addr_octet[1] << 8) |
+ (uint32_t)dev->d_mac.ether_addr_octet[0];
+ stm32_putreg(regval, STM32_ETH_MACA0LR);
+}
+
+/****************************************************************************
+ * Function: stm32_macenable
+ *
+ * Description:
+ * Enable normal MAC operation.
+ *
+ * Parameters:
+ * priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32_macenable(FAR struct stm32_ethmac_s *priv)
+{
+ uint32_t regval;
+
+ /* Set the MAC address */
+
+ stm32_macaddress(priv);
+
+ /* Enable transmit state machine of the MAC for transmission on the MII */
+
+ regval = stm32_getreg(STM32_ETH_MACCR);
+ regval |= ETH_MACCR_TE;
+ stm32_putreg(regval, STM32_ETH_MACCR);
+
+ /* Flush Transmit FIFO */
+
+ regval = stm32_getreg(STM32_ETH_DMAOMR);
+ regval |= ETH_DMAOMR_FTF;
+ stm32_putreg(regval, STM32_ETH_DMAOMR);
+
+ /* Enable receive state machine of the MAC for reception from the MII */
+
+ /* Enables or disables the MAC reception. */
+
+ regval = stm32_getreg(STM32_ETH_MACCR);
+ regval |= ETH_MACCR_RE;
+ stm32_putreg(regval, STM32_ETH_MACCR);
+
+ /* Start DMA transmission */
+
+ regval = stm32_getreg(STM32_ETH_DMAOMR);
+ regval |= ETH_DMAOMR_ST;
+ stm32_putreg(regval, STM32_ETH_DMAOMR);
+
+ /* Start DMA reception */
+
+ regval = stm32_getreg(STM32_ETH_DMAOMR);
+ regval |= ETH_DMAOMR_SR;
+ stm32_putreg(regval, STM32_ETH_DMAOMR);
+
+ /* Enable Ethernet DMA interrupts.
+ *
+ * The STM32 hardware supports two interrupts: (1) one dedicated to normal
+ * Ethernet operations and the other, used only for the Ethernet wakeup
+ * event. The wake-up interrupt is not used by this driver.
+ *
+ * The first Ethernet vector is reserved for interrupts generated by the
+ * MAC and the DMA. The MAC provides PMT and time stamp trigger interrupts,
+ * neither of which are used by this driver.
+ */
+
+ stm32_putreg(ETH_MACIMR_ALLINTS, STM32_ETH_MACIMR);
+
+ /* Ethernet DMA supports two classes of interrupts: Normal interrupt
+ * summary (NIS) and Abnormal interrupt summary (AIS) with a variety
+ * individual normal and abnormal interrupting events. Here only
+ * the normal receive event is enabled (unless DEBUG is enabled). Transmit
+ * events will only be enabled when a transmit interrupt is expected.
+ */
+
+ stm32_putreg((ETH_DMAINT_RECV_ENABLE | ETH_DMAINT_ERROR_ENABLE), STM32_ETH_DMAIER);
+ return OK;
+}
+
+/****************************************************************************
+ * Function: stm32_ethconfig
+ *
+ * Description:
+ * Configure the Ethernet interface for DMA operation.
+ *
+ * Parameters:
+ * priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv)
+{
+ int ret;
+
+ /* NOTE: The Ethernet clocks were initialized early in the boot-up
+ * sequence in stm32_rcc.c.
+ */
+
+ /* Reset the Ethernet block */
+
+ nllvdbg("Reset the Ethernet block\n");
+ stm32_ethreset(priv);
+
+ /* Initialize the PHY */
+
+ nllvdbg("Initialize the PHY\n");
+ ret = stm32_phyinit(priv);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Initialize the MAC and DMA */
+
+ nllvdbg("Initialize the MAC and DMA\n");
+ ret = stm32_macconfig(priv);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Initialize the free buffer list */
+
+ stm32_initbuffer(priv);
+
+ /* Initialize TX Descriptors list: Chain Mode */
+
+ stm32_txdescinit(priv);
+
+ /* Initialize RX Descriptors list: Chain Mode */
+
+ stm32_rxdescinit(priv);
+
+ /* Enable normal MAC operation */
+
+ nllvdbg("Enable normal operation\n");
+ return stm32_macenable(priv);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: stm32_ethinitialize
+ *
+ * Description:
+ * Initialize the Ethernet driver for one interface. If the STM32 chip
+ * supports multiple Ethernet controllers, then board specific logic
+ * must implement up_netinitialize() and call this function to initialize
+ * the desired interfaces.
+ *
+ * Parameters:
+ * intf - In the case where there are multiple EMACs, this value
+ * identifies which EMAC is to be initialized.
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#if STM32_NETHERNET == 1
+static inline
+#endif
+
+int stm32_ethinitialize(int intf)
+{
+ struct stm32_ethmac_s *priv;
+
+ nvdbg("intf: %d\n", intf);
+
+ /* Get the interface structure associated with this interface number. */
+
+ DEBUGASSERT(intf < STM32_NETHERNET);
+ priv = &g_stm32ethmac[intf];
+
+ /* Initialize the driver structure */
+
+ memset(priv, 0, sizeof(struct stm32_ethmac_s));
+ priv->dev.d_ifup = stm32_ifup; /* I/F up (new IP address) callback */
+ priv->dev.d_ifdown = stm32_ifdown; /* I/F down callback */
+ priv->dev.d_txavail = stm32_txavail; /* New TX data callback */
+#ifdef CONFIG_NET_IGMP
+ priv->dev.d_addmac = stm32_addmac; /* Add multicast MAC address */
+ priv->dev.d_rmmac = stm32_rmmac; /* Remove multicast MAC address */
+#endif
+ priv->dev.d_private = (void*)g_stm32ethmac; /* Used to recover private state from dev */
+
+ /* Create a watchdog for timing polling for and timing of transmisstions */
+
+ priv->txpoll = wd_create(); /* Create periodic poll timer */
+ priv->txtimeout = wd_create(); /* Create TX timeout timer */
+
+ /* Configure GPIO pins to support Ethernet */
+
+ stm32_ethgpioconfig(priv);
+
+ /* Attach the IRQ to the driver */
+
+ if (irq_attach(STM32_IRQ_ETH, stm32_interrupt))
+ {
+ /* We could not attach the ISR to the interrupt */
+
+ return -EAGAIN;
+ }
+
+ /* Put the interface in the down state. */
+
+ stm32_ifdown(&priv->dev);
+
+ /* Register the device with the OS so that socket IOCTLs can be performed */
+
+ (void)netdev_register(&priv->dev);
+ return OK;
+}
+
+/****************************************************************************
+ * Function: up_netinitialize
+ *
+ * Description:
+ * This is the "standard" network initialization logic called from the
+ * low-level initialization logic in up_initialize.c. If STM32_NETHERNET
+ * greater than one, then board specific logic will have to supply a
+ * version of up_netinitialize() that calls stm32_ethinitialize() with
+ * the appropriate interface number.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returned Value:
+ * None.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#if STM32_NETHERNET == 1
+void up_netinitialize(void)
+{
+ (void)stm32_ethinitialize(0);
+}
+#endif
+
+#endif /* STM32_NETHERNET > 0 */
+#endif /* CONFIG_NET && CONFIG_STM32_ETHMAC */
diff --git a/nuttx/arch/arm/src/stm32/stm32_eth.h b/nuttx/arch/arm/src/stm32/stm32_eth.h
new file mode 100644
index 000000000..188dc10d3
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_eth.h
@@ -0,0 +1,97 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_eth.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_STM32_ETH_H
+#define __ARCH_ARM_SRC_STM32_STM32_ETH_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+#if STM32_NETHERNET > 0
+
+#include "chip/stm32_eth.h"
+
+#ifndef __ASSEMBLY__
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Function: stm32_ethinitialize
+ *
+ * Description:
+ * Initialize the Ethernet driver for one interface. If the STM32 chip
+ * supports multiple Ethernet controllers, then board specific logic
+ * must implement up_netinitialize() and call this function to initialize
+ * the desired interfaces.
+ *
+ * Parameters:
+ * intf - In the case where there are multiple EMACs, this value
+ * identifies which EMAC is to be initialized.
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ************************************************************************************/
+
+#if STM32_NETHERNET > 1
+EXTERN int stm32_ethinitialize(int intf);
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* STM32_NETHERNET > 0 */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_ETH_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_exti.h b/nuttx/arch/arm/src/stm32/stm32_exti.h
new file mode 100644
index 000000000..6dddf3836
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_exti.h
@@ -0,0 +1,119 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_exti.h
+ *
+ * Copyright (C) 2009, 2012 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_STM32_STM32_EXTI_H
+#define __ARCH_ARM_SRC_STM32_STM32_EXTI_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/irq.h>
+
+#include "chip.h"
+#include "chip/stm32_exti.h"
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_gpiosetevent
+ *
+ * Description:
+ * Sets/clears GPIO based event and interrupt triggers.
+ *
+ * Parameters:
+ * - pinset: gpio pin configuration
+ * - rising/falling edge: enables
+ * - event: generate event when set
+ * - func: when non-NULL, generate interrupt
+ *
+ * Returns:
+ * The previous value of the interrupt handler function pointer. This value may,
+ * for example, be used to restore the previous handler when multiple handlers are
+ * used.
+ *
+ ************************************************************************************/
+
+EXTERN xcpt_t stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge,
+ bool event, xcpt_t func);
+
+/****************************************************************************
+ * Name: stm32_exti_alarm
+ *
+ * Description:
+ * Sets/clears EXTI alarm interrupt.
+ *
+ * Parameters:
+ * - rising/falling edge: enables interrupt on rising/falling edget
+ * - event: generate event when set
+ * - func: when non-NULL, generate interrupt
+ *
+ * Returns:
+ * The previous value of the interrupt handler function pointer. This
+ * value may, for example, be used to restore the previous handler when
+ * multiple handlers are used.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+EXTERN xcpt_t stm32_exti_alarm(bool risingedge, bool fallingedge, bool event,
+ xcpt_t func);
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_EXTI_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_exti_alarm.c b/nuttx/arch/arm/src/stm32/stm32_exti_alarm.c
new file mode 100644
index 000000000..07db26fd4
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_exti_alarm.c
@@ -0,0 +1,167 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_exti_alarm.c
+ *
+ * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ * Diego Sanchez <dsanchez@nx-engineering.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <arch/irq.h>
+
+#include "up_arch.h"
+#include "chip.h"
+#include "stm32_gpio.h"
+#include "stm32_exti.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Interrupt handlers attached to the ALARM EXTI */
+
+static xcpt_t stm32_exti_callback;
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+ /****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_exti_alarm_isr
+ *
+ * Description:
+ * EXTI ALARM interrupt service routine/dispatcher
+ *
+ ****************************************************************************/
+
+static int stm32_exti_alarm_isr(int irq, void *context)
+{
+ int ret = OK;
+
+ /* Clear the pending EXTI interrupt */
+
+ putreg32(EXTI_RTC_ALARM, STM32_EXTI_PR);
+
+ /* And dispatch the interrupt to the handler */
+
+ if (stm32_exti_callback)
+ {
+ ret = stm32_exti_callback(irq, context);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_exti_alarm
+ *
+ * Description:
+ * Sets/clears EXTI alarm interrupt.
+ *
+ * Parameters:
+ * - rising/falling edge: enables interrupt on rising/falling edget
+ * - event: generate event when set
+ * - func: when non-NULL, generate interrupt
+ *
+ * Returns:
+ * The previous value of the interrupt handler function pointer. This
+ * value may, for example, be used to restore the previous handler when
+ * multiple handlers are used.
+ *
+ ****************************************************************************/
+
+xcpt_t stm32_exti_alarm(bool risingedge, bool fallingedge, bool event,
+ xcpt_t func)
+{
+ xcpt_t oldhandler;
+
+ /* Get the previous GPIO IRQ handler; Save the new IRQ handler. */
+
+ oldhandler = stm32_exti_callback;
+ stm32_exti_callback = func;
+
+ /* Install external interrupt handlers (if not already attached) */
+
+ if (func)
+ {
+ irq_attach(STM32_IRQ_RTCALRM, stm32_exti_alarm_isr);
+ up_enable_irq(STM32_IRQ_RTCALRM);
+ }
+ else
+ {
+ up_disable_irq(STM32_IRQ_RTCALRM);
+ }
+
+ /* Configure rising/falling edges */
+
+ modifyreg32(STM32_EXTI_RTSR,
+ risingedge ? 0 : EXTI_RTC_ALARM,
+ risingedge ? EXTI_RTC_ALARM : 0);
+ modifyreg32(STM32_EXTI_FTSR,
+ fallingedge ? 0 : EXTI_RTC_ALARM,
+ fallingedge ? EXTI_RTC_ALARM : 0);
+
+ /* Enable Events and Interrupts */
+
+ modifyreg32(STM32_EXTI_EMR,
+ event ? 0 : EXTI_RTC_ALARM,
+ event ? EXTI_RTC_ALARM : 0);
+ modifyreg32(STM32_EXTI_IMR,
+ func ? 0 : EXTI_RTC_ALARM,
+ func ? EXTI_RTC_ALARM : 0);
+
+ /* Return the old IRQ handler */
+
+ return oldhandler;
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_exti_gpio.c b/nuttx/arch/arm/src/stm32/stm32_exti_gpio.c
new file mode 100644
index 000000000..f897691ef
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_exti_gpio.c
@@ -0,0 +1,337 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_exti_gpio.c
+ *
+ * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ * Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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 <nuttx/irq.h>
+#include <nuttx/arch.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include "up_arch.h"
+#include "chip.h"
+#include "stm32_gpio.h"
+#include "stm32_exti.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Interrupt handlers attached to each EXTI */
+
+static xcpt_t stm32_exti_callbacks[16];
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+ /****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Interrupt Service Routines - Dispatchers
+ ****************************************************************************/
+
+static int stm32_exti0_isr(int irq, void *context)
+{
+ int ret = OK;
+
+ /* Clear the pending interrupt */
+
+ putreg32(0x0001, STM32_EXTI_PR);
+
+ /* And dispatch the interrupt to the handler */
+
+ if (stm32_exti_callbacks[0])
+ {
+ ret = stm32_exti_callbacks[0](irq, context);
+ }
+
+ return ret;
+}
+
+static int stm32_exti1_isr(int irq, void *context)
+{
+ int ret = OK;
+
+ /* Clear the pending interrupt */
+
+ putreg32(0x0002, STM32_EXTI_PR);
+
+ /* And dispatch the interrupt to the handler */
+
+ if (stm32_exti_callbacks[1])
+ {
+ ret = stm32_exti_callbacks[1](irq, context);
+ }
+
+ return ret;
+}
+
+static int stm32_exti2_isr(int irq, void *context)
+{
+ int ret = OK;
+
+ /* Clear the pending interrupt */
+
+ putreg32(0x0004, STM32_EXTI_PR);
+
+ /* And dispatch the interrupt to the handler */
+
+ if (stm32_exti_callbacks[2])
+ {
+ ret = stm32_exti_callbacks[2](irq, context);
+ }
+
+ return ret;
+}
+
+static int stm32_exti3_isr(int irq, void *context)
+{
+ int ret = OK;
+
+ /* Clear the pending interrupt */
+
+ putreg32(0x0008, STM32_EXTI_PR);
+
+ /* And dispatch the interrupt to the handler */
+
+ if (stm32_exti_callbacks[3])
+ {
+ ret = stm32_exti_callbacks[3](irq, context);
+ }
+
+ return ret;
+}
+
+static int stm32_exti4_isr(int irq, void *context)
+{
+ int ret = OK;
+
+ /* Clear the pending interrupt */
+
+ putreg32(0x0010, STM32_EXTI_PR);
+
+ /* And dispatch the interrupt to the handler */
+
+ if (stm32_exti_callbacks[4])
+ {
+ ret = stm32_exti_callbacks[4](irq, context);
+ }
+
+ return ret;
+}
+
+static int stm32_exti_multiisr(int irq, void *context, int first, int last)
+{
+ uint32_t pr;
+ int pin;
+ int ret = OK;
+
+ /* Examine the state of each pin in the group */
+
+ pr = getreg32(STM32_EXTI_PR);
+
+ /* And dispatch the interrupt to the handler */
+
+ for (pin = first; pin <= last; pin++)
+ {
+ /* Is an interrupt pending on this pin? */
+
+ uint32_t mask = (1 << pin);
+ if ((pr & mask) != 0)
+ {
+ /* Clear the pending interrupt */
+
+ putreg32(mask, STM32_EXTI_PR);
+
+ /* And dispatch the interrupt to the handler */
+
+ if (stm32_exti_callbacks[pin])
+ {
+ int tmp = stm32_exti_callbacks[pin](irq, context);
+ if (tmp != OK)
+ {
+ ret = tmp;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int stm32_exti95_isr(int irq, void *context)
+{
+ return stm32_exti_multiisr(irq, context, 5, 9);
+}
+
+static int stm32_exti1510_isr(int irq, void *context)
+{
+ return stm32_exti_multiisr(irq, context, 10, 15);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_gpiosetevent
+ *
+ * Description:
+ * Sets/clears GPIO based event and interrupt triggers.
+ *
+ * Parameters:
+ * - pinset: gpio pin configuration
+ * - rising/falling edge: enables
+ * - event: generate event when set
+ * - func: when non-NULL, generate interrupt
+ *
+ * Returns:
+ * The previous value of the interrupt handler function pointer. This value may,
+ * for example, be used to restore the previous handler when multiple handlers are
+ * used.
+ *
+ ****************************************************************************/
+
+xcpt_t stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge,
+ bool event, xcpt_t func)
+{
+ uint32_t pin = pinset & GPIO_PIN_MASK;
+ uint32_t exti = STM32_EXTI_BIT(pin);
+ int irq;
+ xcpt_t handler;
+ xcpt_t oldhandler = NULL;
+
+ /* Select the interrupt handler for this EXTI pin */
+
+ if (pin < 5)
+ {
+ irq = pin + STM32_IRQ_EXTI0;
+ switch (pin)
+ {
+ case 0:
+ handler = stm32_exti0_isr;
+ break;
+
+ case 1:
+ handler = stm32_exti1_isr;
+ break;
+
+ case 2:
+ handler = stm32_exti2_isr;
+ break;
+
+ case 3:
+ handler = stm32_exti3_isr;
+ break;
+
+ default:
+ handler = stm32_exti4_isr;
+ break;
+ }
+ }
+ else if (pin < 10)
+ {
+ irq = STM32_IRQ_EXTI95;
+ handler = stm32_exti95_isr;
+ }
+ else
+ {
+ irq = STM32_IRQ_EXTI1510;
+ handler = stm32_exti1510_isr;
+ }
+
+ /* Get the previous GPIO IRQ handler; Save the new IRQ handler. */
+
+ oldhandler = stm32_exti_callbacks[pin];
+ stm32_exti_callbacks[pin] = func;
+
+ /* Install external interrupt handlers */
+
+ if (func)
+ {
+ irq_attach(irq, handler);
+ up_enable_irq(irq);
+ }
+ else
+ {
+ up_disable_irq(irq);
+ }
+
+ /* Configure GPIO, enable EXTI line enabled if event or interrupt is
+ * enabled.
+ */
+
+ if (event || func)
+ {
+ pinset |= GPIO_EXTI;
+ }
+
+ stm32_configgpio(pinset);
+
+ /* Configure rising/falling edges */
+
+ modifyreg32(STM32_EXTI_RTSR,
+ risingedge ? 0 : exti,
+ risingedge ? exti : 0);
+ modifyreg32(STM32_EXTI_FTSR,
+ fallingedge ? 0 : exti,
+ fallingedge ? exti : 0);
+
+ /* Enable Events and Interrupts */
+
+ modifyreg32(STM32_EXTI_EMR,
+ event ? 0 : exti,
+ event ? exti : 0);
+ modifyreg32(STM32_EXTI_IMR,
+ func ? 0 : exti,
+ func ? exti : 0);
+
+ /* Return the old IRQ handler */
+
+ return oldhandler;
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_flash.c b/nuttx/arch/arm/src/stm32/stm32_flash.c
new file mode 100644
index 000000000..83fcc6172
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_flash.c
@@ -0,0 +1,247 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_flash.c
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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.
+ *
+ ************************************************************************************/
+
+/* Provides standard flash access functions, to be used by the flash mtd driver.
+ * The interface is defined in the include/nuttx/progmem.h
+ *
+ * Requirements during write/erase operations on FLASH:
+ * - HSI must be ON.
+ * - Low Power Modes are not permitted during write/erase
+ */
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/arch.h>
+#include <errno.h>
+
+#include "stm32_flash.h"
+#include "stm32_rcc.h"
+#include "stm32_waste.h"
+
+#include "up_arch.h"
+
+/* Only for the STM32F10xx family for now */
+
+#ifdef CONFIG_STM32_STM32F10XX
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#define FLASH_KEY1 0x45670123
+#define FLASH_KEY2 0xCDEF89AB
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+void stm32_flash_unlock(void)
+{
+ while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY)
+ {
+ up_waste();
+ }
+
+ if (getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK)
+ {
+ /* Unlock sequence */
+
+ putreg32(FLASH_KEY1, STM32_FLASH_KEYR);
+ putreg32(FLASH_KEY2, STM32_FLASH_KEYR);
+ }
+}
+
+void stm32_flash_lock(void)
+{
+ modifyreg16(STM32_FLASH_CR, 0, FLASH_CR_LOCK);
+}
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+uint16_t up_progmem_npages(void)
+{
+ return STM32_FLASH_NPAGES;
+}
+
+bool up_progmem_isuniform(void)
+{
+ return true;
+}
+
+uint16_t up_progmem_pagesize(uint16_t page)
+{
+ return STM32_FLASH_PAGESIZE;
+}
+
+int up_progmem_getpage(uint32_t addr)
+{
+ if (addr >= STM32_FLASH_SIZE)
+ {
+ return -EFAULT;
+ }
+
+ return addr / STM32_FLASH_PAGESIZE;
+}
+
+int up_progmem_erasepage(uint16_t page)
+{
+ uint32_t addr;
+ uint16_t count;
+
+ if (page >= STM32_FLASH_NPAGES)
+ {
+ return -EFAULT;
+ }
+
+ /* Get flash ready and begin erasing single page */
+
+ if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
+ {
+ return -EPERM;
+ }
+
+ stm32_flash_unlock();
+
+ modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PER);
+ putreg32(page * STM32_FLASH_PAGESIZE, STM32_FLASH_AR);
+ modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT);
+
+ while(getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste();
+
+ modifyreg32(STM32_FLASH_CR, FLASH_CR_PER, 0);
+
+ /* Verify */
+
+ for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
+ count; count-=4, addr += 4)
+ {
+ if (getreg32(addr) != 0xffffffff)
+ {
+ return -EIO;
+ }
+ }
+
+ return STM32_FLASH_PAGESIZE;
+}
+
+int up_progmem_ispageerased(uint16_t page)
+{
+ uint32_t addr;
+ uint16_t count;
+ uint16_t bwritten = 0;
+
+ if (page >= STM32_FLASH_NPAGES)
+ {
+ return -EFAULT;
+ }
+
+ /* Verify */
+
+ for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
+ count; count--, addr++)
+ {
+ if (getreg8(addr) != 0xff)
+ {
+ bwritten++;
+ }
+ }
+
+ return bwritten;
+}
+
+int up_progmem_write(uint32_t addr, const void *buf, size_t count)
+{
+ uint16_t *hword = (uint16_t *)buf;
+ size_t written = count;
+
+ /* STM32 requires half-word access */
+
+ if (count & 1)
+ {
+ return -EINVAL;
+ }
+
+ /* Check for valid address range */
+
+ if ((addr+count) >= STM32_FLASH_SIZE)
+ {
+ return -EFAULT;
+ }
+
+ /* Get flash ready and begin flashing */
+
+ if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
+ {
+ return -EPERM;
+ }
+
+ stm32_flash_unlock();
+
+ modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG);
+
+ for (addr += STM32_FLASH_BASE; count; count--, hword++, addr+=2)
+ {
+ /* Write half-word and wait to complete */
+
+ putreg16(*hword, addr);
+
+ while(getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste();
+
+ /* Verify */
+
+ if (getreg32(STM32_FLASH_SR) & FLASH_SR_WRPRT_ERR)
+ {
+ modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
+ return -EROFS;
+ }
+
+ if (getreg16(addr) != *hword)
+ {
+ modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
+ return -EIO;
+ }
+
+ }
+
+ modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
+ return written;
+}
+
+#endif /* CONFIG_STM32_STM32F10XX */
diff --git a/nuttx/arch/arm/src/stm32/stm32_flash.h b/nuttx/arch/arm/src/stm32/stm32_flash.h
new file mode 100644
index 000000000..10c5cc189
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_flash.h
@@ -0,0 +1,49 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_flash.h
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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_STM32_STM32_FLASH_H
+#define __ARCH_ARM_SRC_STM32_STM32_FLASH_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/progmem.h>
+
+#include "chip.h"
+#include "chip/stm32_flash.h"
+
+#endif /* __ARCH_ARM_SRC_STM32_STM32_FLASH_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_fsmc.h b/nuttx/arch/arm/src/stm32/stm32_fsmc.h
new file mode 100644
index 000000000..9fd4f3fa2
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_fsmc.h
@@ -0,0 +1,304 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_fsmc.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_STM32_FSMC_H
+#define __ARCH_ARM_SRC_STM32_STM32_FSMC_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define STM32_FSMC_BCR_OFFSET(n) (8*((n)-1))
+#define STM32_FSMC_BCR1_OFFSET 0x0000 /* SRAM/NOR-Flash chip-select control registers 1 */
+#define STM32_FSMC_BCR2_OFFSET 0x0008 /* SRAM/NOR-Flash chip-select control registers 2 */
+#define STM32_FSMC_BCR3_OFFSET 0x0010 /* SRAM/NOR-Flash chip-select control registers 3 */
+#define STM32_FSMC_BCR4_OFFSET 0x0018 /* SRAM/NOR-Flash chip-select control registers 4 */
+
+#define STM32_FSMC_BTR_OFFSET(n) (8*((n)-1)+0x0004)
+#define STM32_FSMC_BTR1_OFFSET 0x0004 /* SRAM/NOR-Flash chip-select timing registers 1 */
+#define STM32_FSMC_BTR2_OFFSET 0x000c /* SRAM/NOR-Flash chip-select timing registers 2 */
+#define STM32_FSMC_BTR3_OFFSET 0x0014 /* SRAM/NOR-Flash chip-select timing registers 3 */
+#define STM32_FSMC_BTR4_OFFSET 0x001c /* SRAM/NOR-Flash chip-select timing registers 4 */
+
+#define STM32_FSMC_BWTR_OFFSET(n) (8*((n)-1)+0x0104)
+#define STM32_FSMC_BWTR1_OFFSET 0x0104 /* SRAM/NOR-Flash write timing registers 1 */
+#define STM32_FSMC_BWTR2_OFFSET 0x010c /* SRAM/NOR-Flash write timing registers 2 */
+#define STM32_FSMC_BWTR3_OFFSET 0x0114 /* SRAM/NOR-Flash write timing registers 3 */
+#define STM32_FSMC_BWTR4_OFFSET 0x011c /* SRAM/NOR-Flash write timing registers 4 */
+
+#define STM32_FSMC_PCR_OFFSET(n) (0x0020*((n)-1)+0x0040)
+#define STM32_FSMC_PCR2_OFFSET 0x0060 /* NAND Flash/PC Card controller register 2 */
+#define STM32_FSMC_PCR3_OFFSET 0x0080 /* NAND Flash/PC Card controller register 3 */
+#define STM32_FSMC_PCR4_OFFSET 0x00a0 /* NAND Flash/PC Card controller register 4 */
+
+#define STM32_FSMC_SR_OFFSET(n) (0x0020*((n)-1)+0x0044)
+#define STM32_FSMC_SR2_OFFSET 0x0064 /* NAND Flash/PC Card controller register 2 */
+#define STM32_FSMC_SR3_OFFSET 0x0084 /* NAND Flash/PC Card controller register 3 */
+#define STM32_FSMC_SR4_OFFSET 0x00a4 /* NAND Flash/PC Card controller register 4 */
+
+#define STM32_FSMC_PMEM_OFFSET(n) (0x0020*((n)-1)+0x0048)
+#define STM32_FSMC_PMEM2_OFFSET 0x0068 /* Common memory space timing register 2 */
+#define STM32_FSMC_PMEM3_OFFSET 0x0088 /* Common memory space timing register 3 */
+#define STM32_FSMC_PMEM4_OFFSET 0x00a8 /* Common memory space timing register 4 */
+
+#define STM32_FSMC_PATT_OFFSET(n) (0x0020*((n)-1)+0x004c)
+#define STM32_FSMC_PATT2_OFFSET 0x006c /* Attribute memory space timing register 2 */
+#define STM32_FSMC_PATT3_OFFSET 0x008c /* Attribute memory space timing register 3 */
+#define STM32_FSMC_PATT4_OFFSET 0x00ac /* Attribute memory space timing register 4 */
+
+#define STM32_PIO4_OFFSET 0x00b0 /* I/O space timing register 4 */
+
+#define STM32_FSMC_ECCR_OFFSET(n) (0x0020*((n)-1)+0x003c)
+#define STM32_FSMC_ECCR2_OFFSET 0x0054 /* ECC result register 2 */
+#define STM32_FSMC_ECCR3_OFFSET 0x0074 /* ECC result register 3 */
+
+/* Register Addresses ***************************************************************/
+
+#define STM32_FSMC_BCR(n) (STM32_FSMC_BASE+STM32_FSMC_BCR_OFFSET(n))
+#define STM32_FSMC_BCR1 (STM32_FSMC_BASE+STM32_FSMC_BCR1_OFFSET )
+#define STM32_FSMC_BCR2 (STM32_FSMC_BASE+STM32_FSMC_BCR2_OFFSET )
+#define STM32_FSMC_BCR3 (STM32_FSMC_BASE+STM32_FSMC_BCR3_OFFSET )
+#define STM32_FSMC_BCR4 (STM32_FSMC_BASE+STM32_FSMC_BCR4_OFFSET )
+
+#define STM32_FSMC_BTR(n) (STM32_FSMC_BASE+STM32_FSMC_BTR_OFFSET(n))
+#define STM32_FSMC_BTR1 (STM32_FSMC_BASE+STM32_FSMC_BTR1_OFFSET )
+#define STM32_FSMC_BTR2 (STM32_FSMC_BASE+STM32_FSMC_BTR2_OFFSET )
+#define STM32_FSMC_BTR3 (STM32_FSMC_BASE+STM32_FSMC_BTR3_OFFSET )
+#define STM32_FSMC_BTR4 (STM32_FSMC_BASE+STM32_FSMC_BTR4_OFFSET )
+
+#define STM32_FSMC_BWTR(n) (STM32_FSMC_BASE+STM32_FSMC_BWTR_OFFSET(n))
+#define STM32_FSMC_BWTR1 (STM32_FSMC_BASE+STM32_FSMC_BWTR1_OFFSET )
+#define STM32_FSMC_BWTR2 (STM32_FSMC_BASE+STM32_FSMC_BWTR2_OFFSET )
+#define STM32_FSMC_BWTR3 (STM32_FSMC_BASE+STM32_FSMC_BWTR3_OFFSET )
+#define STM32_FSMC_BWTR4 (STM32_FSMC_BASE+STM32_FSMC_BWTR4_OFFSET )
+
+#define STM32_FSMC_PCR(n) (STM32_FSMC_BASE+STM32_FSMC_PCR_OFFSET(n))
+#define STM32_FSMC_PCR2 (STM32_FSMC_BASE+STM32_FSMC_PCR2_OFFSET )
+#define STM32_FSMC_PCR3 (STM32_FSMC_BASE+STM32_FSMC_PCR3_OFFSET )
+#define STM32_FSMC_PCR4 (STM32_FSMC_BASE+STM32_FSMC_PCR4_OFFSET )
+
+#define STM32_FSMC_SR(n) (STM32_FSMC_BASE+STM32_FSMC_SR_OFFSET(n))
+#define STM32_FSMC_SR2 (STM32_FSMC_BASE+STM32_FSMC_SR2_OFFSET )
+#define STM32_FSMC_SR3 (STM32_FSMC_BASE+STM32_FSMC_SR3_OFFSET )
+#define STM32_FSMC_SR4 (STM32_FSMC_BASE+STM32_FSMC_SR4_OFFSET )
+
+#define STM32_FSMC_PMEM(n) (STM32_FSMC_BASE+STM32_FSMC_PMEM_OFFSET(n))
+#define STM32_FSMC_PMEM2 (STM32_FSMC_BASE+STM32_FSMC_PMEM2_OFFSET )
+#define STM32_FSMC_PMEM3 (STM32_FSMC_BASE+STM32_FSMC_PMEM3_OFFSET )
+#define STM32_FSMC_PMEM4 (STM32_FSMC_BASE+STM32_FSMC_PMEM4_OFFSET )
+
+#define STM32_FSMC_PATT(n) (STM32_FSMC_BASE+STM32_FSMC_PATT_OFFSET(n))
+#define STM32_FSMC_PATT2 (STM32_FSMC_BASE+STM32_FSMC_PATT2_OFFSET )
+#define STM32_FSMC_PATT3 (STM32_FSMC_BASE+STM32_FSMC_PATT3_OFFSET )
+#define STM32_FSMC_PATT4 (STM32_FSMC_BASE+STM32_FSMC_PATT4_OFFSET )
+
+#define STM32_PIO4 (STM32_FSMC_BASE+STM32_FSMC_PIO4_OFFSET )
+
+#define STM32_FSMC_ECCR(n) (STM32_FSMC_BASE+STM32_FSMC_ECCR_OFFSET(n))
+#define STM32_FSMC_ECCR2 (STM32_FSMC_BASE+STM32_FSMC_ECCR2_OFFSET )
+#define STM32_FSMC_ECCR3 (STM32_FSMC_BASE+STM32_FSMC_ECCR3_OFFSET )
+
+/* Register Bitfield Definitions ****************************************************/
+
+#define FSMC_BCR_MBKEN (1 << 0) /* Memory bank enable bit */
+#define FSMC_BCR_MUXEN (1 << 1) /* Address/data multiplexing enable bit */
+#define FSMC_BCR_MTYP_SHIFT (2) /* Memory type */
+#define FSMC_BCR_MTYP_MASK (3 << FSMC_BCR_MTYP_SHIFT)
+# define FSMC_BCR_SRAM (0 << FSMC_BCR_MTYP_SHIFT)
+# define FSMC_BCR_ROM (0 << FSMC_BCR_MTYP_SHIFT)
+# define FSMC_BCR_PSRAM (1 << FSMC_BCR_MTYP_SHIFT)
+# define FSMC_BCR_CRAM (1 << FSMC_BCR_MTYP_SHIFT)
+# define FSMC_BCR_NOR (2 << FSMC_BCR_MTYP_SHIFT)
+#define FSMC_BCR_MWID_SHIFT (4) /* Memory data bus width */
+#define FSMC_BCR_MWID_MASK (3 << FSMC_BCR_MWID_SHIFT)
+# define FSMC_BCR_MWID8 (0 << FSMC_BCR_MWID_SHIFT)
+# define FSMC_BCR_MWID16 (1 << FSMC_BCR_MWID_SHIFT)
+#define FSMC_BCR_FACCEN (1 << 6) /* Flash access enable */
+#define FSMC_BCR_BURSTEN (1 << 8) /* Burst enable bit */
+#define FSMC_BCR_WAITPOL (1 << 9) /* Wait signal polarity bit */
+#define FSMC_BCR_WRAPMOD (1 << 10) /* Wrapped burst mode support */
+#define FSMC_BCR_WAITCFG (1 << 11) /* Wait timing configuration */
+#define FSMC_BCR_WREN (1 << 12) /* Write enable bit */
+#define FSMC_BCR_WAITEN (1 << 13) /* Wait enable bit */
+#define FSMC_BCR_EXTMOD (1 << 14) /* Extended mode enable */
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define FSMC_BCR_ASYNCWAIT (1 << 15) /* Wait signal during asynchronous transfers */
+#endif
+#define FSMC_BCR_CBURSTRW (1 << 19) /* Write burst enable */
+
+#define FSMC_BCR_RSTVALUE 0x000003d2
+
+#define FSMC_BTR_ADDSET_SHIFT (0) /* Address setup phase duration */
+#define FSMC_BTR_ADDSET_MASK (15 << FSMC_BTR_ADDSET_SHIFT)
+# define FSMC_BTR_ADDSET(n) ((n-1) << FSMC_BTR_ADDSET_SHIFT) /* (n)xHCLK n=1..16 */
+#define FSMC_BTR_ADDHLD_SHIFT (4) /* Address-hold phase duration */
+#define FSMC_BTR_ADDHLD_MASK (15 << FSMC_BTR_ADDHLD_SHIFT)
+# define FSMC_BTR_ADDHLD(n) ((n-1) << FSMC_BTR_ADDHLD_SHIFT) /* (n)xHCLK n=2..16*/
+#define FSMC_BTR_DATAST_SHIFT (8) /* Data-phase duration */
+#define FSMC_BTR_DATAST_MASK (255 << FSMC_BTR_DATAST_SHIFT)
+# define FSMC_BTR_DATAST(n) ((n-1) << FSMC_BTR_DATAST_SHIFT) /* (n)xHCLK n=2..256 */
+#define FSMC_BTR_BUSTURN_SHIFT (16) /* Bus turnaround phase duration */
+#define FSMC_BTR_BUSTURN_MASK (15 << FSMC_BTR1_BUSTURN_SHIFT)
+# define FSMC_BTR_BUSTRUN(n) ((n-1) << FSMC_BTR_BUSTURN_SHIFT) /* (n)xHCLK n=1..16 */
+#define FSMC_BTR_CLKDIV_SHIFT (20) /* Clock divide ratio */
+#define FSMC_BTR_CLKDIV_MASK (15 << FSMC_BTR_CLKDIV_SHIFT)
+# define FSMC_BTR_CLKDIV(n) ((n-1) << FSMC_BTR_CLKDIV_SHIFT) /* (n)xHCLK n=2..16 */
+#define FSMC_BTR_DATLAT_SHIFT (24) /* Data latency */
+#define FSMC_BTR_DATLAT_MASK (15 << FSMC_BTR_DATLAT_SHIFT)
+# define FSMC_BTR_DATLAT(n) ((n-2) << FSMC_BTR_DATLAT_SHIFT) /* (n)xHCLK n=2..17 */
+#define FSMC_BTR_ACCMOD_SHIFT (28) /* Access mode */
+#define FSMC_BTR_ACCMOD_MASK (3 << FSMC_BTR_ACCMOD_SHIFT)
+# define FSMC_BTR_ACCMODA (0 << FSMC_BTR_ACCMOD_SHIFT)
+# define FSMC_BTR_ACCMODB (1 << FSMC_BTR_ACCMOD_SHIFT)
+# define FSMC_BTR_ACCMODC (2 << FSMC_BTR_ACCMOD_SHIFT)
+# define FSMC_BTR_ACCMODD (3 << FSMC_BTR_ACCMOD_SHIFT)
+
+#define FSMC_BTR_RSTVALUE 0xffffffff
+
+#define FSMC_BWTR_ADDSET_SHIFT (0) /* Address setup phase duration */
+#define FSMC_BWTR_ADDSET_MASK (15 << FSMC_BWTR_ADDSET_SHIFT)
+# define FSMC_BWTR_ADDSET(n) ((n-1) << FSMC_BWTR_ADDSET_SHIFT) /* (n)xHCLK n=1..16 */
+#define FSMC_BWTR_ADDHLD_SHIFT (4) /* Address-hold phase duration */
+#define FSMC_BWTR_ADDHLD_MASK (15 << FSMC_BWTR_ADDHLD_SHIFT)
+# define FSMC_BWTR_ADDHLD(n) ((n-1) << FSMC_BWTR_ADDHLD_SHIFT) /* (n)xHCLK n=2..16*/
+#define FSMC_BWTR_DATAST_SHIFT (8) /* Data-phase duration */
+#define FSMC_BWTR_DATAST_MASK (255 << FSMC_BWTR_DATAST_SHIFT)
+# define FSMC_BWTR_DATAST(n) ((n-1) << FSMC_BWTR_DATAST_SHIFT) /* (n)xHCLK n=2..256 */
+#define FSMC_BWTR_CLKDIV_SHIFT (20) /* Clock divide ratio */
+#define FSMC_BWTR_CLKDIV_MASK (15 << FSMC_BWTR_CLKDIV_SHIFT)
+# define FSMC_BWTR_CLKDIV(n) ((n-1) << FSMC_BWTR_CLKDIV_SHIFT) /* (n)xHCLK n=2..16 */
+#define FSMC_BWTR_DATLAT_SHIFT (24) /* Data latency */
+#define FSMC_BWTR_DATLAT_MASK (15 << FSMC_BWTR_DATLAT_SHIFT)
+# define FSMC_BWTR_DATLAT(n) ((n-2) << FSMC_BWTR_DATLAT_SHIFT) /* (n)xHCLK n=2..17 */
+#define FSMC_BWTR_ACCMOD_SHIFT (28) /* Access mode */
+#define FSMC_BWTR_ACCMOD_MASK (3 << FSMC_BWTR_ACCMOD_SHIFT)
+# define FSMC_BWTR_ACCMODA (0 << FSMC_BWTR_ACCMOD_SHIFT)
+# define FSMC_BWTR_ACCMODB (1 << FSMC_BWTR_ACCMOD_SHIFT)
+# define FSMC_BWTR_ACCMODC (2 << FSMC_BWTR_ACCMOD_SHIFT)
+# define FSMC_BWTR_ACCMODD (3 << FSMC_BTR_ACCMOD_SHIFT)
+
+#define FSMC_PCR_PWAITEN (1 << 1) /* Wait feature enable bit */
+#define FSMC_PCR_PBKEN (1 << 2) /* PC Card/NAND Flash memory bank enable bit */
+#define FSMC_PCR_PTYP (1 << 3) /* Memory type */
+#define FSMC_PCR_PWID_SHIFT (4) /* NAND Flash databus width */
+#define FSMC_PCR_PWID_MASK (3 << FSMC_PCR_PWID_SHIFT)
+# define FSMC_PCR_PWID8 (0 << FSMC_PCR_PWID_SHIFT)
+# define FSMC_PCR_PWID16 (1 << FSMC_PCR_PWID_SHIFT)
+#define FSMC_PCR_ECCEN (1 << 6) /* ECC computation logic enable bit */
+#define FSMC_PCR_TCLR_SHIFT (9) /* CLE to RE delay */
+#define FSMC_PCR_TCLR_MASK (15 << FSMC_PCR_TCLR_SHIFT)
+# define FSMC_PCR_TCLR(n) ((n-1) << FSMC_PCR_TCLR_SHIFT) /* (n)xHCLK n=1..16 */
+#define FSMC_PCR_TAR_SHIFT (13) /* ALE to RE delay */
+#define FSMC_PCR_TAR_MASK (15 << FSMC_PCR_TAR_MASK)
+# define FSMC_PCR_TAR(n) ((n-1) << FSMC_PCR_TAR_SHIFT) /* (n)xHCLK n=1..16 */
+#define FSMC_PCR_ECCPS_SHIFT (17) /* ECC page size */
+#define FSMC_PCR_ECCPS_MASK (7 << FSMC_PCR_ECCPS_SHIFT)
+# define FSMC_PCR_ECCPS256 (0 << FSMC_PCR_ECCPS_SHIFT) /* 256 bytes */
+# define FSMC_PCR_ECCPS512 (1 << FSMC_PCR_ECCPS_SHIFT) /* 512 bytes */
+# define FSMC_PCR_ECCPS1024 (2 << FSMC_PCR_ECCPS_SHIFT) /* 1024 bytes */
+# define FSMC_PCR_ECCPS2048 (3 << FSMC_PCR_ECCPS_SHIFT) /* 2048 bytes */
+# define FSMC_PCR_ECCPS4096 (4 << FSMC_PCR_ECCPS_SHIFT) /* 8192 bytes */
+# define FSMC_PCR_ECCPS8192 (5 << FSMC_PCR_ECCPS_SHIFT) /* 1024 bytes */
+
+#define FSMC_SR_IRS (1 << 0) /* Interrupt Rising Edge status */
+#define FSMC_SR_ILS (1 << 1) /* Interrupt Level status */
+#define FSMC_SR_IFS (1 << 2) /* Interrupt Falling Edge status */
+#define FSMC_SR_IREN (1 << 3) /* Interrupt Rising Edge detection Enable bit */
+#define FSMC_SR_ILEN (1 << 4) /* Interrupt Level detection Enable bit */
+#define FSMC_SR_IFEN (1 << 5) /* Interrupt Falling Edge detection Enable bit */
+#define FSMC_SR_FEMPT (1 << 6) /* FIFO empty */
+
+#define FSMC_PMEM_MEMSET_SHIFT (0) /* Common memory setup time */
+#define FSMC_PMEM_MEMSET_MASK (255 << FSMC_PMEM_MEMSET_SHIFT)
+# define FSMC_PMEM_MEMSET(n) ((n-1) << FSMC_PMEM_MEMSET_SHIFT) /* (n)xHCLK n=1..256 */
+#define FSMC_PMEM_MEMWAIT_SHIFT (8) /* Common memory wait time */
+#define FSMC_PMEM_MEMWAIT_MASK (255 << FSMC_PMEM_MEMWAIT_SHIFT)
+# define FSMC_PMEM_MEMWAIT(n) ((n-1) << FSMC_PMEM_MEMWAIT_SHIFT) /* (n)xHCLK n=2..256 */
+#define FSMC_PMEM_MEMHOLD_SHIFT (16) /* Common memoryhold time */
+#define FSMC_PMEM_MEMHOLD_MASK (255 << FSMC_PMEM_MEMHOLD_SHIFT)
+# define FSMC_PMEM_MEMHOLD(n) ((n) << FSMC_PMEM_MEMHOLD_SHIFT) /* (n)xHCLK n=1..255 */
+#define FSMC_PMEM_MEMHIZ_SHIFT (24) /* Common memory databus HiZ time */
+#define FSMC_PMEM_MEMHIZ_MASK (255 << FSMC_PMEM_MEMHIZ_SHIFT)
+# define FSMC_PMEM_MEMHIZ(n) ((n) << FSMC_PMEM_MEMHIZ_SHIFT) /* (n)xHCLK n=0..255 */
+
+#define FSMC_PATT_ATTSET_SHIFT (0) /* Attribute memory setup time */
+#define FSMC_PATT_ATTSET_MASK (255 << FSMC_PATT_ATTSET_SHIFT)
+# define FSMC_PATT_ATTSET(n) ((n-1) << FSMC_PATT_ATTSET_SHIFT) /* (n)xHCLK n=1..256 */
+#define FSMC_PATT_ATTWAIT_SHIFT (8) /* Attribute memory wait time */
+#define FSMC_PATT_ATTWAIT_MASK (255 << FSMC_PATT_ATTWAIT_SHIFT)
+# define FSMC_PATT_ATTWAIT(n) ((n-1) << FSMC_PATT_ATTWAIT_SHIFT) /* (n)xHCLK n=2..256 */
+#define FSMC_PATT_ATTHOLD_SHIFT (16) /* Attribute memory hold time */
+#define FSMC_PATT_ATTHOLD_MASK (255 << FSMC_PATT_ATTHOLD_SHIFT)
+# define FSMC_PATT_ATTHOLD(n) ((n) << FSMC_PATT_ATTHOLD_SHIFT) /* (n)xHCLK n=1..255 */
+#define FSMC_PATT_ATTHIZ_SHIFT (24) /* Attribute memory databus HiZ time */
+#define FSMC_PATT_ATTHIZ_MASK (255 << FSMC_PATT_ATTHIZ_SHIFT)
+# define FSMC_PATT_ATTHIZ(n) ((n) << FSMC_PATT_ATTHIZ_SHIFT) /* (n)xHCLK n=0..255 */
+
+#define FSMC_PIO4_IOSET_SHIFT (0) /* IOribute memory setup time */
+#define FSMC_PIO4_IOSET_MASK (255 << FSMC_PIO4_IOSET_SHIFT)
+# define FSMC_PIO4_IOSET(n) ((n-1) << FSMC_PIO4_IOSET_SHIFT) /* (n)xHCLK n=1..256 */
+#define FSMC_PIO4_IOWAIT_SHIFT (8) /* IOribute memory wait time */
+#define FSMC_PIO4_IOWAIT_MASK (255 << FSMC_PIO4_IOWAIT_SHIFT)
+# define FSMC_PIO4_IOWAIT(n) ((n-1) << FSMC_PIO4_IOWAIT_SHIFT) /* (n)xHCLK n=2..256 */
+#define FSMC_PIO4_IOHOLD_SHIFT (16) /* IOribute memory hold time */
+#define FSMC_PIO4_IOHOLD_MASK (255 << FSMC_PIO4_IOHOLD_SHIFT)
+# define FSMC_PIO4_IOHOLD(n) ((n) << FSMC_PIO4_IOHOLD_SHIFT) /* (n)xHCLK n=1..255 */
+#define FSMC_PIO4_IOHIZ_SHIFT (24) /* IOribute memory databus HiZ time */
+#define FSMC_PIO4_IOHIZ_MASK (255 << FSMC_PIO4_IOHIZ_SHIFT)
+# define FSMC_PIO4_IOHIZ(n) ((n) << FSMC_PIO4_IOHIZ_SHIFT) /* (n)xHCLK n=0..255 */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_STM32_STM32_FSMC_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_gpio.c b/nuttx/arch/arm/src/stm32/stm32_gpio.c
new file mode 100644
index 000000000..143e48a2c
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_gpio.c
@@ -0,0 +1,736 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_gpio.c
+ *
+ * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ * Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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 <errno.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include "up_arch.h"
+
+#include "chip.h"
+#include "stm32_gpio.h"
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32_syscfg.h"
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+/* Base addresses for each GPIO block */
+
+const uint32_t g_gpiobase[STM32_NGPIO_PORTS] =
+{
+#if STM32_NGPIO_PORTS > 0
+ STM32_GPIOA_BASE,
+#endif
+#if STM32_NGPIO_PORTS > 1
+ STM32_GPIOB_BASE,
+#endif
+#if STM32_NGPIO_PORTS > 2
+ STM32_GPIOC_BASE,
+#endif
+#if STM32_NGPIO_PORTS > 3
+ STM32_GPIOD_BASE,
+#endif
+#if STM32_NGPIO_PORTS > 4
+ STM32_GPIOE_BASE,
+#endif
+#if STM32_NGPIO_PORTS > 5
+ STM32_GPIOF_BASE,
+#endif
+#if STM32_NGPIO_PORTS > 6
+ STM32_GPIOG_BASE,
+#endif
+#if STM32_NGPIO_PORTS > 7
+ STM32_GPIOH_BASE,
+#endif
+#if STM32_NGPIO_PORTS > 8
+ STM32_GPIOI_BASE,
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: stm32_gpioremap
+ *
+ * Description:
+ *
+ * Based on configuration within the .config file, this function will
+ * remaps positions of alternative functions.
+ *
+ ****************************************************************************/
+
+static inline void stm32_gpioremap(void)
+{
+#if defined(CONFIG_STM32_STM32F10XX)
+
+ /* Remap according to the configuration within .config file */
+
+ uint32_t val = 0;
+
+#ifdef CONFIG_STM32_JTAG_FULL_ENABLE
+ /* The reset default */
+#elif CONFIG_STM32_JTAG_NOJNTRST_ENABLE
+ val |= AFIO_MAPR_SWJ; /* enabled but without JNTRST */
+#elif CONFIG_STM32_JTAG_SW_ENABLE
+ val |= AFIO_MAPR_SWDP; /* set JTAG-DP disabled and SW-DP enabled */
+#else
+ val |= AFIO_MAPR_DISAB; /* set JTAG-DP and SW-DP Disabled */
+#endif
+
+#ifdef CONFIG_STM32_TIM1_FULL_REMAP
+ val |= AFIO_MAPR_TIM1_FULLREMAP;
+#endif
+#ifdef CONFIG_STM32_TIM1_PARTIAL_REMAP
+ val |= AFIO_MAPR_TIM1_PARTREMAP;
+#endif
+#ifdef CONFIG_STM32_TIM2_FULL_REMAP
+ val |= AFIO_MAPR_TIM2_FULLREMAP;
+#endif
+#ifdef CONFIG_STM32_TIM2_PARTIAL_REMAP_1
+ val |= AFIO_MAPR_TIM2_PARTREMAP1;
+#endif
+#ifdef CONFIG_STM32_TIM2_PARTIAL_REMAP_2
+ val |= AFIO_MAPR_TIM2_PARTREMAP2;
+#endif
+#ifdef CONFIG_STM32_TIM3_FULL_REMAP
+ val |= AFIO_MAPR_TIM3_FULLREMAP;
+#endif
+#ifdef CONFIG_STM32_TIM3_PARTIAL_REMAP
+ val |= AFIO_MAPR_TIM3_PARTREMAP;
+#endif
+#ifdef CONFIG_STM32_TIM4_REMAP
+ val |= AFIO_MAPR_TIM4_REMAP;
+#endif
+
+#ifdef CONFIG_STM32_USART1_REMAP
+ val |= AFIO_MAPR_USART1_REMAP;
+#endif
+#ifdef CONFIG_STM32_USART2_REMAP
+ val |= AFIO_MAPR_USART2_REMAP;
+#endif
+#ifdef CONFIG_STM32_USART3_FULL_REMAP
+ val |= AFIO_MAPR_USART3_FULLREMAP;
+#endif
+#ifdef CONFIG_STM32_USART3_PARTIAL_REMAP
+ val |= AFIO_MAPR_USART3_PARTREMAP;
+#endif
+
+#ifdef CONFIG_STM32_SPI1_REMAP
+ val |= AFIO_MAPR_SPI1_REMAP;
+#endif
+#ifdef CONFIG_STM32_SPI3_REMAP
+#endif
+
+#ifdef CONFIG_STM32_I2C1_REMAP
+ val |= AFIO_MAPR_I2C1_REMAP;
+#endif
+
+#ifdef CONFIG_STM32_CAN1_REMAP1
+ val |= AFIO_MAPR_PB89;
+#endif
+#ifdef CONFIG_STM32_CAN1_REMAP2
+ val |= AFIO_MAPR_PD01;
+#endif
+
+ putreg32(val, STM32_AFIO_MAPR);
+#endif
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: stm32_gpioinit
+ *
+ * Description:
+ * Based on configuration within the .config file, it does:
+ * - Remaps positions of alternative functions.
+ *
+ * Typically called from stm32_start().
+ *
+ * Assumptions:
+ * This function is called early in the initialization sequence so that
+ * no mutual exlusion is necessary.
+ *
+ ****************************************************************************/
+
+void stm32_gpioinit(void)
+{
+ /* Remap according to the configuration within .config file */
+
+ stm32_gpioremap();
+}
+
+/****************************************************************************
+ * Name: stm32_configgpio
+ *
+ * Description:
+ * Configure a GPIO pin based on bit-encoded description of the pin.
+ * Once it is configured as Alternative (GPIO_ALT|GPIO_CNF_AFPP|...)
+ * function, it must be unconfigured with stm32_unconfiggpio() with
+ * the same cfgset first before it can be set to non-alternative function.
+ *
+ * Returns:
+ * OK on success
+ * A negated errono valu on invalid port, or when pin is locked as ALT
+ * function.
+ *
+ * To-Do: Auto Power Enable
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_configgpio (for the STM32F10xxx family)
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F10XX)
+int stm32_configgpio(uint32_t cfgset)
+{
+ uint32_t base;
+ uint32_t cr;
+ uint32_t regval;
+ uint32_t regaddr;
+ unsigned int port;
+ unsigned int pin;
+ unsigned int pos;
+ unsigned int modecnf;
+ irqstate_t flags;
+ bool input;
+
+ /* Verify that this hardware supports the select GPIO port */
+
+ port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+ if (port >= STM32_NGPIO_PORTS)
+ {
+ return -EINVAL;
+ }
+
+ /* Get the port base address */
+
+ base = g_gpiobase[port];
+
+ /* Get the pin number and select the port configuration register for that
+ * pin
+ */
+
+ pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+ if (pin < 8)
+ {
+ cr = base + STM32_GPIO_CRL_OFFSET;
+ pos = pin;
+ }
+ else
+ {
+ cr = base + STM32_GPIO_CRH_OFFSET;
+ pos = pin - 8;
+ }
+
+ /* Input or output? */
+
+ input = ((cfgset & GPIO_INPUT) != 0);
+
+ /* Interrupts must be disabled from here on out so that we have mutually
+ * exclusive access to all of the GPIO configuration registers.
+ */
+
+ flags = irqsave();
+
+ /* Decode the mode and configuration */
+
+ regval = getreg32(cr);
+
+ if (input)
+ {
+ /* Input.. force mode = INPUT */
+
+ modecnf = 0;
+ }
+ else
+ {
+ /* Output or alternate function */
+
+ modecnf = (cfgset & GPIO_MODE_MASK) >> GPIO_MODE_SHIFT;
+ }
+
+ modecnf |= ((cfgset & GPIO_CNF_MASK) >> GPIO_CNF_SHIFT) << 2;
+
+ /* Set the port configuration register */
+
+ regval &= ~(GPIO_CR_MODECNF_MASK(pos));
+ regval |= (modecnf << GPIO_CR_MODECNF_SHIFT(pos));
+ putreg32(regval, cr);
+
+ /* Set or reset the corresponding BRR/BSRR bit */
+
+ if (!input)
+ {
+ /* It is an output or an alternate function. We have to look at the CNF
+ * bits to know which.
+ */
+
+ unsigned int cnf = (cfgset & GPIO_CNF_MASK);
+ if (cnf != GPIO_CNF_OUTPP && cnf != GPIO_CNF_OUTOD)
+ {
+ /* Its an alternate function pin... we can return early */
+
+ irqrestore(flags);
+ return OK;
+ }
+ }
+ else
+ {
+ /* It is an input pin... Should it configured as an EXTI interrupt? */
+
+ if ((cfgset & GPIO_EXTI) != 0)
+ {
+ int shift;
+
+ /* Yes.. Set the bits in the EXTI CR register */
+
+ regaddr = STM32_AFIO_EXTICR(pin);
+ regval = getreg32(regaddr);
+ shift = AFIO_EXTICR_EXTI_SHIFT(pin);
+ regval &= ~(AFIO_EXTICR_PORT_MASK << shift);
+ regval |= (((uint32_t)port) << shift);
+
+ putreg32(regval, regaddr);
+ }
+
+ if ((cfgset & GPIO_CNF_MASK) != GPIO_CNF_INPULLUD)
+ {
+ /* Neither... we can return early */
+
+ irqrestore(flags);
+ return OK;
+ }
+ }
+
+ /* If it is an output... set the pin to the correct initial state.
+ * If it is pull-down or pull up, then we need to set the ODR
+ * appropriately for that function.
+ */
+
+ if ((cfgset & GPIO_OUTPUT_SET) != 0)
+ {
+ /* Use the BSRR register to set the output */
+
+ regaddr = base + STM32_GPIO_BSRR_OFFSET;
+ }
+ else
+ {
+ /* Use the BRR register to clear */
+
+ regaddr = base + STM32_GPIO_BRR_OFFSET;
+ }
+
+ regval = getreg32(regaddr);
+ regval |= (1 << pin);
+ putreg32(regval, regaddr);
+
+ irqrestore(flags);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_configgpio (for the STM2F20xxx and STM32F40xxx family)
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+int stm32_configgpio(uint32_t cfgset)
+{
+ uintptr_t base;
+ uint32_t regval;
+ uint32_t setting;
+ unsigned int regoffset;
+ unsigned int port;
+ unsigned int pin;
+ unsigned int pos;
+ unsigned int pinmode;
+ irqstate_t flags;
+
+ /* Verify that this hardware supports the select GPIO port */
+
+ port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+ if (port >= STM32_NGPIO_PORTS)
+ {
+ return -EINVAL;
+ }
+
+ /* Get the port base address */
+
+ base = g_gpiobase[port];
+
+ /* Get the pin number and select the port configuration register for that
+ * pin
+ */
+
+ pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+
+ /* Set up the mode register (and remember whether the pin mode) */
+
+ switch (cfgset & GPIO_MODE_MASK)
+ {
+ default:
+ case GPIO_INPUT: /* Input mode */
+ pinmode = GPIO_MODER_INPUT;
+ break;
+
+ case GPIO_OUTPUT: /* General purpose output mode */
+ pinmode = GPIO_MODER_OUTPUT;
+ break;
+
+ case GPIO_ALT: /* Alternate function mode */
+ pinmode = GPIO_MODER_ALT;
+ break;
+
+ case GPIO_ANALOG: /* Analog mode */
+ pinmode = GPIO_MODER_ANALOG;
+ break;
+ }
+
+ /* Interrupts must be disabled from here on out so that we have mutually
+ * exclusive access to all of the GPIO configuration registers.
+ */
+
+ flags = irqsave();
+
+ /* Now apply the configuration to the mode register */
+
+ regval = getreg32(base + STM32_GPIO_MODER_OFFSET);
+ regval &= ~GPIO_MODER_MASK(pin);
+ regval |= ((uint32_t)pinmode << GPIO_MODER_SHIFT(pin));
+ putreg32(regval, base + STM32_GPIO_MODER_OFFSET);
+
+ /* Set up the pull-up/pull-down configuration (all but analog pins) */
+
+ setting = GPIO_PUPDR_NONE;
+ if (pinmode != GPIO_MODER_ANALOG)
+ {
+ switch (cfgset & GPIO_PUPD_MASK)
+ {
+ default:
+ case GPIO_FLOAT: /* No pull-up, pull-down */
+ break;
+
+ case GPIO_PULLUP: /* Pull-up */
+ setting = GPIO_PUPDR_PULLUP;
+ break;
+
+ case GPIO_PULLDOWN: /* Pull-down */
+ setting = GPIO_PUPDR_PULLDOWN;
+ break;
+ }
+ }
+
+ regval = getreg32(base + STM32_GPIO_PUPDR_OFFSET);
+ regval &= ~GPIO_PUPDR_MASK(pin);
+ regval |= (setting << GPIO_PUPDR_SHIFT(pin));
+ putreg32(regval, base + STM32_GPIO_PUPDR_OFFSET);
+
+ /* Set the alternate function (Only alternate function pins) */
+
+ if (pinmode == GPIO_MODER_ALT)
+ {
+ setting = (cfgset & GPIO_AF_MASK) >> GPIO_AF_SHIFT;
+ }
+ else
+ {
+ setting = 0;
+ }
+
+ if (pin < 8)
+ {
+ regoffset = STM32_GPIO_AFRL_OFFSET;
+ pos = pin;
+ }
+ else
+ {
+ regoffset = STM32_GPIO_ARFH_OFFSET;
+ pos = pin - 8;
+ }
+
+ regval = getreg32(base + regoffset);
+ regval &= ~GPIO_AFR_MASK(pos);
+ regval |= (setting << GPIO_AFR_SHIFT(pos));
+ putreg32(regval, base + regoffset);
+
+ /* Set speed (Only outputs and alternate function pins) */
+
+ if (pinmode == GPIO_MODER_OUTPUT || pinmode == GPIO_MODER_ALT)
+ {
+ switch (cfgset & GPIO_SPEED_MASK)
+ {
+ default:
+ case GPIO_SPEED_2MHz: /* 2 MHz Low speed output */
+ setting = GPIO_OSPEED_2MHz;
+ break;
+
+ case GPIO_SPEED_25MHz: /* 25 MHz Medium speed output */
+ setting = GPIO_OSPEED_25MHz;
+ break;
+
+ case GPIO_SPEED_50MHz: /* 50 MHz Fast speed output */
+ setting = GPIO_OSPEED_50MHz;
+ break;
+
+ case GPIO_SPEED_100MHz: /* 100 MHz High speed output */
+ setting = GPIO_OSPEED_100MHz;
+ break;
+ }
+ }
+ else
+ {
+ setting = 0;
+ }
+
+ regval = getreg32(base + STM32_GPIO_OSPEED_OFFSET);
+ regval &= ~GPIO_OSPEED_MASK(pin);
+ regval |= (setting << GPIO_OSPEED_SHIFT(pin));
+ putreg32(regval, base + STM32_GPIO_OSPEED_OFFSET);
+
+ /* Set push-pull/open-drain (Only outputs and alternate function pins) */
+
+ regval = getreg32(base + STM32_GPIO_OTYPER_OFFSET);
+ setting = GPIO_OTYPER_OD(pin);
+
+ if ((pinmode == GPIO_MODER_OUTPUT || pinmode == GPIO_MODER_ALT) &&
+ (cfgset & GPIO_OPENDRAIN) != 0)
+ {
+ regval |= setting;
+ }
+ else
+ {
+ regval &= ~setting;
+ }
+
+ putreg32(regval, base + STM32_GPIO_OTYPER_OFFSET);
+
+ /* If it is an output... set the pin to the correct initial state. */
+
+ if (pinmode == GPIO_MODER_OUTPUT)
+ {
+ bool value = ((cfgset & GPIO_OUTPUT_SET) != 0);
+ stm32_gpiowrite(cfgset, value);
+ }
+
+ /* Otherwise, it is an input pin. Should it configured as an EXTI interrupt? */
+
+ else if ((cfgset & GPIO_EXTI) != 0)
+ {
+ /* "In STM32 F1 the selection of the EXTI line source is performed through
+ * the EXTIx bits in the AFIO_EXTICRx registers, while in F2 series this
+ * selection is done through the EXTIx bits in the SYSCFG_EXTICRx registers.
+ *
+ * "Only the mapping of the EXTICRx registers has been changed, without any
+ * changes to the meaning of the EXTIx bits. However, the range of EXTI
+ * bits values has been extended to 0b1000 to support the two ports added
+ * in F2, port H and I (in F1 series the maximum value is 0b0110)."
+ */
+
+ uint32_t regaddr;
+ int shift;
+
+ /* Set the bits in the SYSCFG EXTICR register */
+
+ regaddr = STM32_SYSCFG_EXTICR(pin);
+ regval = getreg32(regaddr);
+ shift = SYSCFG_EXTICR_EXTI_SHIFT(pin);
+ regval &= ~(SYSCFG_EXTICR_PORT_MASK << shift);
+ regval |= (((uint32_t)port) << shift);
+
+ putreg32(regval, regaddr);
+ }
+
+ irqrestore(flags);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_unconfiggpio
+ *
+ * Description:
+ * Unconfigure a GPIO pin based on bit-encoded description of the pin, set it
+ * into default HiZ state (and possibly mark it's unused) and unlock it whether
+ * it was previsouly selected as alternative function (GPIO_ALT|GPIO_CNF_AFPP|...).
+ *
+ * This is a safety function and prevents hardware from schocks, as unexpected
+ * write to the Timer Channel Output GPIO to fixed '1' or '0' while it should
+ * operate in PWM mode could produce excessive on-board currents and trigger
+ * over-current/alarm function.
+ *
+ * Returns:
+ * OK on success
+ * A negated errno value on invalid port
+ *
+ * To-Do: Auto Power Disable
+ ****************************************************************************/
+
+int stm32_unconfiggpio(uint32_t cfgset)
+{
+ /* Reuse port and pin number and set it to default HiZ INPUT */
+
+ cfgset &= GPIO_PORT_MASK | GPIO_PIN_MASK;
+#if defined(CONFIG_STM32_STM32F10XX)
+ cfgset |= GPIO_INPUT | GPIO_CNF_INFLOAT | GPIO_MODE_INPUT;
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ cfgset |= GPIO_INPUT | GPIO_FLOAT;
+#else
+# error "Unsupported STM32 chip"
+#endif
+
+ /* To-Do: Mark its unuse for automatic power saving options */
+
+ return stm32_configgpio(cfgset);
+}
+
+/****************************************************************************
+ * Name: stm32_gpiowrite
+ *
+ * Description:
+ * Write one or zero to the selected GPIO pin
+ *
+ ****************************************************************************/
+
+void stm32_gpiowrite(uint32_t pinset, bool value)
+{
+ uint32_t base;
+#if defined(CONFIG_STM32_STM32F10XX)
+ uint32_t offset;
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ uint32_t bit;
+#endif
+ unsigned int port;
+ unsigned int pin;
+
+ port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+ if (port < STM32_NGPIO_PORTS)
+ {
+ /* Get the port base address */
+
+ base = g_gpiobase[port];
+
+ /* Get the pin number */
+
+ pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+
+ /* Set or clear the output on the pin */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+
+ if (value)
+ {
+ offset = STM32_GPIO_BSRR_OFFSET;
+ }
+ else
+ {
+ offset = STM32_GPIO_BRR_OFFSET;
+ }
+
+ putreg32((1 << pin), base + offset);
+
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+
+ if (value)
+ {
+ bit = GPIO_BSRR_SET(pin);
+ }
+ else
+ {
+ bit = GPIO_BSRR_RESET(pin);
+ }
+
+ putreg32(bit, base + STM32_GPIO_BSRR_OFFSET);
+
+#else
+# error "Unsupported STM32 chip"
+#endif
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_gpioread
+ *
+ * Description:
+ * Read one or zero from the selected GPIO pin
+ *
+ ****************************************************************************/
+
+bool stm32_gpioread(uint32_t pinset)
+{
+ uint32_t base;
+ unsigned int port;
+ unsigned int pin;
+
+ port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+ if (port < STM32_NGPIO_PORTS)
+ {
+ /* Get the port base address */
+
+ base = g_gpiobase[port];
+
+ /* Get the pin number and return the input state of that pin */
+
+ pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
+ return ((getreg32(base + STM32_GPIO_IDR_OFFSET) & (1 << pin)) != 0);
+ }
+ return 0;
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_gpio.h b/nuttx/arch/arm/src/stm32/stm32_gpio.h
new file mode 100644
index 000000000..34623c525
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_gpio.h
@@ -0,0 +1,514 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_gpio.h
+ *
+ * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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_STM32_STM32_GPIO_H
+#define __ARCH_ARM_SRC_STM32_STM32_GPIO_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifndef __ASSEMBLY__
+# include <stdint.h>
+# include <stdbool.h>
+#endif
+
+#include <nuttx/irq.h>
+
+#include "chip.h"
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "chip/stm32f10xxx_gpio.h"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/stm32f20xxx_gpio.h"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32f40xxx_gpio.h"
+#else
+# error "Unrecognized STM32 chip"
+#endif
+
+/************************************************************************************
+ * Pre-Processor Declarations
+ ************************************************************************************/
+
+/* Bit-encoded input to stm32_configgpio() */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+
+/* 16-bit Encoding:
+ *
+ * 1111 1100 0000 0000
+ * 5432 1098 7654 3210
+ * ---- ---- ---- ----
+ * OFFS SX.. VPPP BBBB
+ */
+
+/* Output mode:
+ *
+ * 1111 1100 0000 0000
+ * 5432 1098 7654 3210
+ * ---- ---- ---- ----
+ * O... .... .... ....
+ */
+
+#define GPIO_INPUT (1 << 15) /* Bit 15: 1=Input mode */
+#define GPIO_OUTPUT (0) /* 0=Output or alternate function */
+#define GPIO_ALT (0)
+
+/* If the pin is a GPIO digital output, then this identifies the initial output value.
+ * If the pin is an input, this bit is overloaded to provide the qualifier to\
+ * distinquish input pull-up and -down:
+ *
+ * 1111 1100 0000 0000
+ * 5432 1098 7654 3210
+ * ---- ---- ---- ----
+ * .... .... V... ....
+ */
+
+#define GPIO_OUTPUT_SET (1 << 7) /* Bit 7: If output, inital value of output */
+#define GPIO_OUTPUT_CLEAR (0)
+
+/* These bits set the primary function of the pin:
+ *
+ * 1111 1100 0000 0000
+ * 5432 1098 7654 3210
+ * ---- ---- ---- ----
+ * .FF. .... .... ....
+ */
+
+#define GPIO_CNF_SHIFT 13 /* Bits 13-14: GPIO function */
+#define GPIO_CNF_MASK (3 << GPIO_CNF_SHIFT)
+
+# define GPIO_CNF_ANALOGIN (0 << GPIO_CNF_SHIFT) /* Analog input */
+# define GPIO_CNF_INFLOAT (1 << GPIO_CNF_SHIFT) /* Input floating */
+# define GPIO_CNF_INPULLUD (2 << GPIO_CNF_SHIFT) /* Input pull-up/down general bit, since up is composed of two parts */
+# define GPIO_CNF_INPULLDWN (2 << GPIO_CNF_SHIFT) /* Input pull-down */
+# define GPIO_CNF_INPULLUP ((2 << GPIO_CNF_SHIFT) | GPIO_OUTPUT_SET) /* Input pull-up */
+
+# define GPIO_CNF_OUTPP (0 << GPIO_CNF_SHIFT) /* Output push-pull */
+# define GPIO_CNF_OUTOD (1 << GPIO_CNF_SHIFT) /* Output open-drain */
+# define GPIO_CNF_AFPP (2 << GPIO_CNF_SHIFT) /* Alternate function push-pull */
+# define GPIO_CNF_AFOD (3 << GPIO_CNF_SHIFT) /* Alternate function open-drain */
+
+/* Maximum frequency selection:
+ *
+ * 1111 1100 0000 0000
+ * 5432 1098 7654 3210
+ * ---- ---- ---- ----
+ * ...S S... .... ....
+ */
+
+#define GPIO_MODE_SHIFT 11 /* Bits 11-12: GPIO frequency selection */
+#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT)
+# define GPIO_MODE_INPUT (0 << GPIO_MODE_SHIFT) /* Input mode (reset state) */
+# define GPIO_MODE_10MHz (1 << GPIO_MODE_SHIFT) /* Output mode, max speed 10 MHz */
+# define GPIO_MODE_2MHz (2 << GPIO_MODE_SHIFT) /* Output mode, max speed 2 MHz */
+# define GPIO_MODE_50MHz (3 << GPIO_MODE_SHIFT) /* Output mode, max speed 50 MHz */
+
+/* External interrupt selection (GPIO inputs only):
+ *
+ * 1111 1100 0000 0000
+ * 5432 1098 7654 3210
+ * ---- ---- ---- ----
+ * .... .X.. .... ....
+ */
+
+#define GPIO_EXTI (1 << 10) /* Bit 10: Configure as EXTI interrupt */
+
+/* This identifies the GPIO port:
+ *
+ * 1111 1100 0000 0000
+ * 5432 1098 7654 3210
+ * ---- ---- ---- ----
+ * .... .... .PPP ....
+ */
+
+#define GPIO_PORT_SHIFT 4 /* Bit 4-6: Port number */
+#define GPIO_PORT_MASK (7 << GPIO_PORT_SHIFT)
+# define GPIO_PORTA (0 << GPIO_PORT_SHIFT) /* GPIOA */
+# define GPIO_PORTB (1 << GPIO_PORT_SHIFT) /* GPIOB */
+# define GPIO_PORTC (2 << GPIO_PORT_SHIFT) /* GPIOC */
+# define GPIO_PORTD (3 << GPIO_PORT_SHIFT) /* GPIOD */
+# define GPIO_PORTE (4 << GPIO_PORT_SHIFT) /* GPIOE */
+# define GPIO_PORTF (5 << GPIO_PORT_SHIFT) /* GPIOF */
+# define GPIO_PORTG (6 << GPIO_PORT_SHIFT) /* GPIOG */
+
+/* This identifies the bit in the port:
+ *
+ * 1111 1100 0000 0000
+ * 5432 1098 7654 3210
+ * ---- ---- ---- ----
+ * .... .... .... BBBB
+ */
+
+#define GPIO_PIN_SHIFT 0 /* Bits 0-3: GPIO number: 0-15 */
+#define GPIO_PIN_MASK (15 << GPIO_PIN_SHIFT)
+#define GPIO_PIN0 (0 << GPIO_PIN_SHIFT)
+#define GPIO_PIN1 (1 << GPIO_PIN_SHIFT)
+#define GPIO_PIN2 (2 << GPIO_PIN_SHIFT)
+#define GPIO_PIN3 (3 << GPIO_PIN_SHIFT)
+#define GPIO_PIN4 (4 << GPIO_PIN_SHIFT)
+#define GPIO_PIN5 (5 << GPIO_PIN_SHIFT)
+#define GPIO_PIN6 (6 << GPIO_PIN_SHIFT)
+#define GPIO_PIN7 (7 << GPIO_PIN_SHIFT)
+#define GPIO_PIN8 (8 << GPIO_PIN_SHIFT)
+#define GPIO_PIN9 (9 << GPIO_PIN_SHIFT)
+#define GPIO_PIN10 (10 << GPIO_PIN_SHIFT)
+#define GPIO_PIN11 (11 << GPIO_PIN_SHIFT)
+#define GPIO_PIN12 (12 << GPIO_PIN_SHIFT)
+#define GPIO_PIN13 (13 << GPIO_PIN_SHIFT)
+#define GPIO_PIN14 (14 << GPIO_PIN_SHIFT)
+#define GPIO_PIN15 (15 << GPIO_PIN_SHIFT)
+
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+
+/* Each port bit of the general-purpose I/O (GPIO) ports can be individually configured
+ * by software in several modes:
+ *
+ * - Input floating
+ * - Input pull-up
+ * - Input-pull-down
+ * - Output open-drain with pull-up or pull-down capability
+ * - Output push-pull with pull-up or pull-down capability
+ * - Alternate function push-pull with pull-up or pull-down capability
+ * - Alternate function open-drain with pull-up or pull-down capability
+ * - Analog
+ *
+ * 20-bit Encoding: 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * Inputs: MMUU .... ...X PPPP BBBB
+ * Outputs: MMUU .... FFOV PPPP BBBB
+ * Alternate Functions: MMUU AAAA FFO. PPPP BBBB
+ * Analog: MM.. .... .... PPPP BBBB
+ */
+
+/* Mode:
+ *
+ * 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * MM.. .... .... .... ....
+ */
+
+#define GPIO_MODE_SHIFT (18) /* Bits 18-19: GPIO port mode */
+#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT)
+# define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* Input mode */
+# define GPIO_OUTPUT (1 << GPIO_MODE_SHIFT) /* General purpose output mode */
+# define GPIO_ALT (2 << GPIO_MODE_SHIFT) /* Alternate function mode */
+# define GPIO_ANALOG (3 << GPIO_MODE_SHIFT) /* Analog mode */
+
+/* Input/output pull-ups/downs (not used with analog):
+ *
+ * 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * ..UU .... .... .... ....
+ */
+
+#define GPIO_PUPD_SHIFT (16) /* Bits 16-17: Pull-up/pull down */
+#define GPIO_PUPD_MASK (3 << GPIO_PUPD_SHIFT)
+# define GPIO_FLOAT (0 << GPIO_PUPD_SHIFT) /* No pull-up, pull-down */
+# define GPIO_PULLUP (1 << GPIO_PUPD_SHIFT) /* Pull-up */
+# define GPIO_PULLDOWN (2 << GPIO_PUPD_SHIFT) /* Pull-down */
+
+/* Alternate Functions:
+ *
+ * 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * .... AAAA .... .... ....
+ */
+
+#define GPIO_AF_SHIFT (12) /* Bits 12-15: Alternate function */
+#define GPIO_AF_MASK (15 << GPIO_AF_SHIFT)
+# define GPIO_AF(n) ((n) << GPIO_AF_SHIFT)
+# define GPIO_AF0 (0 << GPIO_AF_SHIFT)
+# define GPIO_AF1 (1 << GPIO_AF_SHIFT)
+# define GPIO_AF2 (2 << GPIO_AF_SHIFT)
+# define GPIO_AF3 (3 << GPIO_AF_SHIFT)
+# define GPIO_AF4 (4 << GPIO_AF_SHIFT)
+# define GPIO_AF5 (5 << GPIO_AF_SHIFT)
+# define GPIO_AF6 (6 << GPIO_AF_SHIFT)
+# define GPIO_AF7 (7 << GPIO_AF_SHIFT)
+# define GPIO_AF8 (8 << GPIO_AF_SHIFT)
+# define GPIO_AF9 (9 << GPIO_AF_SHIFT)
+# define GPIO_AF10 (10 << GPIO_AF_SHIFT)
+# define GPIO_AF11 (11 << GPIO_AF_SHIFT)
+# define GPIO_AF12 (12 << GPIO_AF_SHIFT)
+# define GPIO_AF13 (13 << GPIO_AF_SHIFT)
+# define GPIO_AF14 (14 << GPIO_AF_SHIFT)
+# define GPIO_AF15 (15 << GPIO_AF_SHIFT)
+
+/* Output/Alt function frequency selection:
+ *
+ * 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * .... .... FF.. .... ....
+ */
+
+#define GPIO_SPEED_SHIFT (10) /* Bits 10-11: GPIO frequency selection */
+#define GPIO_SPEED_MASK (3 << GPIO_SPEED_SHIFT)
+# define GPIO_SPEED_2MHz (0 << GPIO_SPEED_SHIFT) /* 2 MHz Low speed output */
+# define GPIO_SPEED_25MHz (1 << GPIO_SPEED_SHIFT) /* 25 MHz Medium speed output */
+# define GPIO_SPEED_50MHz (2 << GPIO_SPEED_SHIFT) /* 50 MHz Fast speed output */
+# define GPIO_SPEED_100MHz (3 << GPIO_SPEED_SHIFT) /* 100 MHz High speed output */
+
+/* Output/Alt function type selection:
+ *
+ * 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * .... .... ..O. .... ....
+ */
+
+#define GPIO_OPENDRAIN (1 << 9) /* Bit9: 1=Open-drain output */
+#define GPIO_PUSHPULL (0) /* Bit9: 0=Push-pull output */
+
+/* If the pin is a GPIO digital output, then this identifies the initial output value.
+ * If the pin is an input, this bit is overloaded to provide the qualifier to
+ * distinquish input pull-up and -down:
+ *
+ * 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * .... .... ...V .... ....
+ */
+
+#define GPIO_OUTPUT_SET (1 << 8) /* Bit 8: If output, inital value of output */
+#define GPIO_OUTPUT_CLEAR (0)
+
+/* External interrupt selection (GPIO inputs only):
+ *
+ * 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * .... .... ...X .... ....
+ */
+
+#define GPIO_EXTI (1 << 8) /* Bit 8: Configure as EXTI interrupt */
+
+/* This identifies the GPIO port:
+ *
+ * 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * .... .... .... PPPP ....
+ */
+
+#define GPIO_PORT_SHIFT (4) /* Bit 4-7: Port number */
+#define GPIO_PORT_MASK (15 << GPIO_PORT_SHIFT)
+# define GPIO_PORTA (0 << GPIO_PORT_SHIFT) /* GPIOA */
+# define GPIO_PORTB (1 << GPIO_PORT_SHIFT) /* GPIOB */
+# define GPIO_PORTC (2 << GPIO_PORT_SHIFT) /* GPIOC */
+# define GPIO_PORTD (3 << GPIO_PORT_SHIFT) /* GPIOD */
+# define GPIO_PORTE (4 << GPIO_PORT_SHIFT) /* GPIOE */
+# define GPIO_PORTF (5 << GPIO_PORT_SHIFT) /* GPIOF */
+# define GPIO_PORTG (6 << GPIO_PORT_SHIFT) /* GPIOG */
+# define GPIO_PORTH (7 << GPIO_PORT_SHIFT) /* GPIOH */
+# define GPIO_PORTI (8 << GPIO_PORT_SHIFT) /* GPIOI */
+
+/* This identifies the bit in the port:
+ *
+ * 1111 1111 1100 0000 0000
+ * 9876 5432 1098 7654 3210
+ * ---- ---- ---- ---- ----
+ * .... .... .... .... BBBB
+ */
+
+#define GPIO_PIN_SHIFT (0) /* Bits 0-3: GPIO number: 0-15 */
+#define GPIO_PIN_MASK (15 << GPIO_PIN_SHIFT)
+# define GPIO_PIN0 (0 << GPIO_PIN_SHIFT)
+# define GPIO_PIN1 (1 << GPIO_PIN_SHIFT)
+# define GPIO_PIN2 (2 << GPIO_PIN_SHIFT)
+# define GPIO_PIN3 (3 << GPIO_PIN_SHIFT)
+# define GPIO_PIN4 (4 << GPIO_PIN_SHIFT)
+# define GPIO_PIN5 (5 << GPIO_PIN_SHIFT)
+# define GPIO_PIN6 (6 << GPIO_PIN_SHIFT)
+# define GPIO_PIN7 (7 << GPIO_PIN_SHIFT)
+# define GPIO_PIN8 (8 << GPIO_PIN_SHIFT)
+# define GPIO_PIN9 (9 << GPIO_PIN_SHIFT)
+# define GPIO_PIN10 (10 << GPIO_PIN_SHIFT)
+# define GPIO_PIN11 (11 << GPIO_PIN_SHIFT)
+# define GPIO_PIN12 (12 << GPIO_PIN_SHIFT)
+# define GPIO_PIN13 (13 << GPIO_PIN_SHIFT)
+# define GPIO_PIN14 (14 << GPIO_PIN_SHIFT)
+# define GPIO_PIN15 (15 << GPIO_PIN_SHIFT)
+
+#else
+# error "Unrecognized STM32 chip"
+#endif
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/* Base addresses for each GPIO block */
+
+EXTERN const uint32_t g_gpiobase[STM32_NGPIO_PORTS];
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_configgpio
+ *
+ * Description:
+ * Configure a GPIO pin based on bit-encoded description of the pin.
+ * Once it is configured as Alternative (GPIO_ALT|GPIO_CNF_AFPP|...)
+ * function, it must be unconfigured with stm32_unconfiggpio() with
+ * the same cfgset first before it can be set to non-alternative function.
+ *
+ * Returns:
+ * OK on success
+ * ERROR on invalid port, or when pin is locked as ALT function.
+ *
+ ************************************************************************************/
+
+EXTERN int stm32_configgpio(uint32_t cfgset);
+
+/************************************************************************************
+ * Name: stm32_unconfiggpio
+ *
+ * Description:
+ * Unconfigure a GPIO pin based on bit-encoded description of the pin, set it
+ * into default HiZ state (and possibly mark it's unused) and unlock it whether
+ * it was previsouly selected as alternative function (GPIO_ALT|GPIO_CNF_AFPP|...).
+ *
+ * This is a safety function and prevents hardware from schocks, as unexpected
+ * write to the Timer Channel Output GPIO to fixed '1' or '0' while it should
+ * operate in PWM mode could produce excessive on-board currents and trigger
+ * over-current/alarm function.
+ *
+ * Returns:
+ * OK on success
+ * ERROR on invalid port
+ *
+ ************************************************************************************/
+
+EXTERN int stm32_unconfiggpio(uint32_t cfgset);
+
+/************************************************************************************
+ * Name: stm32_gpiowrite
+ *
+ * Description:
+ * Write one or zero to the selected GPIO pin
+ *
+ ************************************************************************************/
+
+EXTERN void stm32_gpiowrite(uint32_t pinset, bool value);
+
+/************************************************************************************
+ * Name: stm32_gpioread
+ *
+ * Description:
+ * Read one or zero from the selected GPIO pin
+ *
+ ************************************************************************************/
+
+EXTERN bool stm32_gpioread(uint32_t pinset);
+
+/************************************************************************************
+ * Name: stm32_gpiosetevent
+ *
+ * Description:
+ * Sets/clears GPIO based event and interrupt triggers.
+ *
+ * Parameters:
+ * - pinset: gpio pin configuration
+ * - rising/falling edge: enables
+ * - event: generate event when set
+ * - func: when non-NULL, generate interrupt
+ *
+ * Returns:
+ * The previous value of the interrupt handler function pointer. This value may,
+ * for example, be used to restore the previous handler when multiple handlers are
+ * used.
+ *
+ ************************************************************************************/
+
+EXTERN xcpt_t stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge,
+ bool event, xcpt_t func);
+
+/************************************************************************************
+ * Function: stm32_dumpgpio
+ *
+ * Description:
+ * Dump all GPIO registers associated with the provided base address
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_DEBUG
+EXTERN int stm32_dumpgpio(uint32_t pinset, const char *msg);
+#else
+# define stm32_dumpgpio(p,m)
+#endif
+
+/************************************************************************************
+ * Function: stm32_gpioinit
+ *
+ * Description:
+ * Based on configuration within the .config file, it does:
+ * - Remaps positions of alternative functions.
+ *
+ * Typically called from stm32_start().
+ *
+ ************************************************************************************/
+
+EXTERN void stm32_gpioinit(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_GPIO_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_i2c.c b/nuttx/arch/arm/src/stm32/stm32_i2c.c
new file mode 100644
index 000000000..d02115a15
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_i2c.c
@@ -0,0 +1,2137 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_i2c.c
+ * STM32 I2C Hardware Layer - Device Driver
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With extensions, modifications by:
+ *
+ * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregroy 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.
+ *
+ ************************************************************************************/
+
+/* Supports:
+ * - Master operation, 100 kHz (standard) and 400 kHz (full speed)
+ * - Multiple instances (shared bus)
+ * - Interrupt based operation
+ *
+ * Structure naming:
+ * - Device: structure as defined by the nuttx/i2c/i2c.h
+ * - Instance: represents each individual access to the I2C driver, obtained by
+ * the i2c_init(); it extends the Device structure from the nuttx/i2c/i2c.h;
+ * Instance points to OPS, to common I2C Hardware private data and contains
+ * its own private data, as frequency, address, mode of operation (in the future)
+ * - Private: Private data of an I2C Hardware
+ *
+ * TODO
+ * - Check for all possible deadlocks (as BUSY='1' I2C needs to be reset in HW using the I2C_CR1_SWRST)
+ * - SMBus support (hardware layer timings are already supported) and add SMBA gpio pin
+ * - Slave support with multiple addresses (on multiple instances):
+ * - 2 x 7-bit address or
+ * - 1 x 10 bit adresses + 1 x 7 bit address (?)
+ * - plus the broadcast address (general call)
+ * - Multi-master support
+ * - DMA (to get rid of too many CPU wake-ups and interventions)
+ * - Be ready for IPMI
+ */
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/i2c.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/clock.h>
+
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+
+#include "stm32_rcc.h"
+#include "stm32_i2c.h"
+#include "stm32_waste.h"
+
+#if defined(CONFIG_STM32_I2C1) || defined(CONFIG_STM32_I2C2) || defined(CONFIG_STM32_I2C3)
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* CONFIG_I2C_POLLED may be set so that I2C interrrupts will not be used. Instead,
+ * CPU-intensive polling will be used.
+ */
+
+/* Interrupt wait timeout in seconds and milliseconds */
+
+#if !defined(CONFIG_STM32_I2CTIMEOSEC) && !defined(CONFIG_STM32_I2CTIMEOMS)
+# define CONFIG_STM32_I2CTIMEOSEC 0
+# define CONFIG_STM32_I2CTIMEOMS 500 /* Default is 500 milliseconds */
+#elif !defined(CONFIG_STM32_I2CTIMEOSEC)
+# define CONFIG_STM32_I2CTIMEOSEC 0 /* User provided milliseconds */
+#elif !defined(CONFIG_STM32_I2CTIMEOMS)
+# define CONFIG_STM32_I2CTIMEOMS 0 /* User provided seconds */
+#endif
+
+/* Interrupt wait time timeout in system timer ticks */
+
+#define CONFIG_STM32_I2CTIMEOTICKS \
+ (SEC2TICK(CONFIG_STM32_I2CTIMEOSEC) + MSEC2TICK(CONFIG_STM32_I2CTIMEOMS))
+
+/* On the STM32F103ZE, there is an internal conflict between I2C1 and FSMC. In that
+ * case, it is necessary to disable FSMC before each I2C1 access and re-enable FSMC
+ * when the I2C access completes.
+ */
+
+#undef I2C1_FSMC_CONFLICT
+#if defined(CONFIG_STM32_STM32F10XX) && defined(CONFIG_STM32_FSMC) && defined(CONFIG_STM32_I2C1)
+# define I2C1_FSMC_CONFLICT
+#endif
+
+/* Debug ****************************************************************************/
+/* CONFIG_DEBUG_I2C + CONFIG_DEBUG enables general I2C debug output. */
+
+#ifdef CONFIG_DEBUG_I2C
+# define i2cdbg dbg
+# define i2cvdbg vdbg
+#else
+# define i2cdbg(x...)
+# define i2cvdbg(x...)
+#endif
+
+/* I2C event trace logic. NOTE: trace uses the internal, non-standard, low-level
+ * debug interface lib_rawprintf() but does not require that any other debug
+ * is enabled.
+ */
+
+#ifndef CONFIG_I2C_TRACE
+# define stm32_i2c_tracereset(p)
+# define stm32_i2c_tracenew(p,s)
+# define stm32_i2c_traceevent(p,e,a)
+# define stm32_i2c_tracedump(p)
+#endif
+
+#ifndef CONFIG_I2C_NTRACE
+# define CONFIG_I2C_NTRACE 32
+#endif
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+/* Interrupt state */
+
+enum stm32_intstate_e
+{
+ INTSTATE_IDLE = 0, /* No I2C activity */
+ INTSTATE_WAITING, /* Waiting for completion of interrupt activity */
+ INTSTATE_DONE, /* Interrupt activity complete */
+};
+
+/* Trace events */
+
+enum stm32_trace_e
+{
+ I2CEVENT_NONE = 0, /* No events have occurred with this status */
+ I2CEVENT_SENDADDR, /* Start/Master bit set and address sent, param = msgc */
+ I2CEVENT_SENDBYTE, /* Send byte, param = dcnt */
+ I2CEVENT_ITBUFEN, /* Enable buffer interrupts, param = 0 */
+ I2CEVENT_RCVBYTE, /* Read more dta, param = dcnt */
+ I2CEVENT_REITBUFEN, /* Re-enable buffer interrupts, param = 0 */
+ I2CEVENT_DISITBUFEN, /* Disable buffer interrupts, param = 0 */
+ I2CEVENT_BTFNOSTART, /* BTF on last byte with no restart, param = msgc */
+ I2CEVENT_BTFRESTART, /* Last byte sent, re-starting, param = msgc */
+ I2CEVENT_BTFSTOP, /* Last byte sten, send stop, param = 0 */
+ I2CEVENT_ERROR /* Error occurred, param = 0 */
+};
+
+/* Trace data */
+
+struct stm32_trace_s
+{
+ uint32_t status; /* I2C 32-bit SR2|SR1 status */
+ uint32_t count; /* Interrupt count when status change */
+ enum stm32_intstate_e event; /* Last event that occurred with this status */
+ uint32_t parm; /* Parameter associated with the event */
+ uint32_t time; /* First of event or first status */
+};
+
+/* I2C Device Private Data */
+
+struct stm32_i2c_priv_s
+{
+ uint32_t base; /* I2C base address */
+ int refs; /* Referernce count */
+ sem_t sem_excl; /* Mutual exclusion semaphore */
+#ifndef CONFIG_I2C_POLLED
+ sem_t sem_isr; /* Interrupt wait semaphore */
+#endif
+ volatile uint8_t intstate; /* Interrupt handshake (see enum stm32_intstate_e) */
+
+ uint8_t msgc; /* Message count */
+ struct i2c_msg_s *msgv; /* Message list */
+ uint8_t *ptr; /* Current message buffer */
+ int dcnt; /* Current message length */
+ uint16_t flags; /* Current message flags */
+
+ /* I2C trace support */
+
+#ifdef CONFIG_I2C_TRACE
+ int tndx; /* Trace array index */
+ uint32_t start_time; /* Time when the trace was started */
+
+ /* The actual trace data */
+
+ struct stm32_trace_s trace[CONFIG_I2C_NTRACE];
+#endif
+
+ uint32_t status; /* End of transfer SR2|SR1 status */
+};
+
+/* I2C Device, Instance */
+
+struct stm32_i2c_inst_s
+{
+ struct i2c_ops_s *ops; /* Standard I2C operations */
+ struct stm32_i2c_priv_s *priv; /* Common driver private data structure */
+
+ uint32_t frequency; /* Frequency used in this instantiation */
+ int address; /* Address used in this instantiation */
+ uint16_t flags; /* Flags used in this instantiation */
+};
+
+/************************************************************************************
+ * Private Function Prototypes
+ ************************************************************************************/
+
+static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
+ uint8_t offset);
+static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
+ uint16_t value);
+static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv,
+ uint8_t offset, uint16_t clearbits,
+ uint16_t setbits);
+static inline void stm32_i2c_sem_wait(FAR struct i2c_dev_s *dev);
+static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv, int timeout_us);
+static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv, int timeout_us);
+static inline void stm32_i2c_sem_post(FAR struct i2c_dev_s *dev);
+static inline void stm32_i2c_sem_init(FAR struct i2c_dev_s *dev);
+static inline void stm32_i2c_sem_destroy(FAR struct i2c_dev_s *dev);
+#ifdef CONFIG_I2C_TRACE
+static void stm32_i2c_tracereset(FAR struct stm32_i2c_priv_s *priv);
+static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv, uint32_t status);
+static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
+ enum stm32_trace_e event, uint32_t parm);
+static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv);
+#endif
+static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv,
+ uint32_t frequency);
+static inline void stm32_i2c_sendstart(FAR struct stm32_i2c_priv_s *priv);
+static inline void stm32_i2c_clrstart(FAR struct stm32_i2c_priv_s *priv);
+static inline void stm32_i2c_sendstop(FAR struct stm32_i2c_priv_s *priv);
+static inline uint32_t stm32_i2c_getstatus(FAR struct stm32_i2c_priv_s *priv);
+#ifdef I2C1_FSMC_CONFLICT
+static inline uint32_t stm32_i2c_disablefsmc(FAR struct stm32_i2c_priv_s *priv);
+static inline void stm32_i2c_enablefsmc(uint32_t ahbenr);
+#endif
+static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv);
+#ifndef CONFIG_I2C_POLLED
+#ifdef CONFIG_STM32_I2C1
+static int stm32_i2c1_isr(int irq, void *context);
+#endif
+#ifdef CONFIG_STM32_I2C2
+static int stm32_i2c2_isr(int irq, void *context);
+#endif
+#ifdef CONFIG_STM32_I2C3
+static int stm32_i2c3_isr(int irq, void *context);
+#endif
+#endif
+static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
+static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
+static uint32_t stm32_i2c_setfrequency(FAR struct i2c_dev_s *dev,
+ uint32_t frequency);
+static int stm32_i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits);
+static int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs,
+ int count);
+static int stm32_i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer,
+ int buflen);
+static int stm32_i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen);
+#ifdef CONFIG_I2C_WRITEREAD
+static int stm32_i2c_writeread(FAR struct i2c_dev_s *dev,
+ const uint8_t *wbuffer, int wbuflen,
+ uint8_t *buffer, int buflen);
+#endif
+#ifdef CONFIG_I2C_TRANSFER
+static int stm32_i2c_transfer(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs,
+ int count);
+#endif
+
+/************************************************************************************
+ * Private Data
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_I2C1
+struct stm32_i2c_priv_s stm32_i2c1_priv =
+{
+ .base = STM32_I2C1_BASE,
+ .refs = 0,
+ .intstate = INTSTATE_IDLE,
+ .msgc = 0,
+ .msgv = NULL,
+ .ptr = NULL,
+ .dcnt = 0,
+ .flags = 0,
+ .status = 0
+};
+#endif
+
+#ifdef CONFIG_STM32_I2C2
+struct stm32_i2c_priv_s stm32_i2c2_priv =
+{
+ .base = STM32_I2C2_BASE,
+ .refs = 0,
+ .intstate = INTSTATE_IDLE,
+ .msgc = 0,
+ .msgv = NULL,
+ .ptr = NULL,
+ .dcnt = 0,
+ .flags = 0,
+ .status = 0
+};
+#endif
+
+#ifdef CONFIG_STM32_I2C3
+struct stm32_i2c_priv_s stm32_i2c3_priv =
+{
+ .base = STM32_I2C3_BASE,
+ .refs = 0,
+ .intstate = INTSTATE_IDLE,
+ .msgc = 0,
+ .msgv = NULL,
+ .ptr = NULL,
+ .dcnt = 0,
+ .flags = 0,
+ .status = 0
+};
+#endif
+
+
+/* Device Structures, Instantiation */
+
+struct i2c_ops_s stm32_i2c_ops =
+{
+ .setfrequency = stm32_i2c_setfrequency,
+ .setaddress = stm32_i2c_setaddress,
+ .write = stm32_i2c_write,
+ .read = stm32_i2c_read
+#ifdef CONFIG_I2C_WRITEREAD
+ , .writeread = stm32_i2c_writeread
+#endif
+#ifdef CONFIG_I2C_TRANSFER
+ , .transfer = stm32_i2c_transfer
+#endif
+#ifdef CONFIG_I2C_SLAVE
+ , .setownaddress = stm32_i2c_setownaddress,
+ .registercallback = stm32_i2c_registercallback
+#endif
+};
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_i2c_getreg
+ *
+ * Description:
+ * Get register value by offset
+ *
+ ************************************************************************************/
+
+static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
+ uint8_t offset)
+{
+ return getreg16(priv->base + offset);
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_putreg
+ *
+ * Description:
+ * Put register value by offset
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
+ uint16_t value)
+{
+ putreg16(value, priv->base + offset);
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_modifyreg
+ *
+ * Description:
+ * Modify register value by offset
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv,
+ uint8_t offset, uint16_t clearbits,
+ uint16_t setbits)
+{
+ modifyreg16(priv->base + offset, clearbits, setbits);
+}
+
+/************************************************************************************
+ * Name:
+ *
+ * Description:
+ *
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_sem_wait(FAR struct i2c_dev_s *dev)
+{
+ while (sem_wait(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl) != 0)
+ {
+ ASSERT(errno == EINTR);
+ }
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_sem_waitdone
+ *
+ * Description:
+ * Wait for a transfer to complete
+ *
+ ************************************************************************************/
+
+#ifndef CONFIG_I2C_POLLED
+static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv, int timeout_us)
+{
+ struct timespec abstime;
+ irqstate_t flags;
+ uint32_t regval;
+ int ret;
+
+ flags = irqsave();
+
+ /* Enable I2C interrupts */
+
+ regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
+ regval |= (I2C_CR2_ITERREN | I2C_CR2_ITEVFEN);
+ stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
+
+ /* Signal the interrupt handler that we are waiting. NOTE: Interrupts
+ * are currently disabled but will be temporarily re-enabled below when
+ * sem_timedwait() sleeps.
+ */
+
+ priv->intstate = INTSTATE_WAITING;
+ do
+ {
+ /* Get the current time */
+
+ (void)clock_gettime(CLOCK_REALTIME, &abstime);
+
+ /* Calculate a time in the future */
+
+#if CONFIG_STM32_I2CTIMEOSEC > 0
+ abstime.tv_sec += CONFIG_STM32_I2CTIMEOSEC;
+#endif
+#if CONFIG_STM32_I2CTIMEOUS_PER_BYTE > 0
+
+ /* Count the number of bytes left to process */
+ int i;
+ int bytecount = 0;
+ for (i = 0; i < priv->msgc; i++)
+ {
+ bytecount += priv->msgv[i].length;
+ }
+
+ abstime.tv_nsec += (CONFIG_STM32_I2CTIMEOUS_PER_BYTE * bytecount) * 1000;
+ if (abstime.tv_nsec > 1000 * 1000 * 1000)
+ {
+ abstime.tv_sec++;
+ abstime.tv_nsec -= 1000 * 1000 * 1000;
+ }
+#else
+ #if CONFIG_STM32_I2CTIMEOMS > 0
+ abstime.tv_nsec += CONFIG_STM32_I2CTIMEOMS * 1000 * 1000;
+ if (abstime.tv_nsec > 1000 * 1000 * 1000)
+ {
+ abstime.tv_sec++;
+ abstime.tv_nsec -= 1000 * 1000 * 1000;
+ }
+ #endif
+#endif
+ /* Wait until either the transfer is complete or the timeout expires */
+
+ ret = sem_timedwait(&priv->sem_isr, &abstime);
+ if (ret != OK && errno != EINTR)
+ {
+ /* Break out of the loop on irrecoverable errors. This would
+ * include timeouts and mystery errors reported by sem_timedwait.
+ * NOTE that we try again if we are awakened by a signal (EINTR).
+ */
+
+ break;
+ }
+ }
+
+ /* Loop until the interrupt level transfer is complete. */
+
+ while (priv->intstate != INTSTATE_DONE);
+
+ /* Set the interrupt state back to IDLE */
+
+ priv->intstate = INTSTATE_IDLE;
+
+ /* Disable I2C interrupts */
+
+ regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
+ regval &= ~I2C_CR2_ALLINTS;
+ stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
+
+ irqrestore(flags);
+ return ret;
+}
+#else
+static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv, int timeout_us)
+{
+ uint32_t start;
+ uint32_t elapsed;
+ int ret;
+
+ /* Signal the interrupt handler that we are waiting. NOTE: Interrupts
+ * are currently disabled but will be temporarily re-enabled below when
+ * sem_timedwait() sleeps.
+ */
+
+ priv->intstate = INTSTATE_WAITING;
+ start = clock_systimer();
+
+ do
+ {
+ /* Poll by simply calling the timer interrupt handler until it
+ * reports that it is done.
+ */
+
+ stm32_i2c_isr(priv);
+
+ /* Calculate the elapsed time */
+
+ elapsed = clock_systimer() - start;
+ }
+
+ /* Loop until the transfer is complete. */
+ while (priv->intstate != INTSTATE_DONE && elapsed < USEC2TICK(timeout_us));
+
+ i2cvdbg("intstate: %d elapsed: %d threshold: %d status: %08x\n",
+ priv->intstate, elapsed, USEC2TICK(timeout_us), priv->status);
+
+ /* Set the interrupt state back to IDLE */
+
+ ret = priv->intstate == INTSTATE_DONE ? OK : -ETIMEDOUT;
+ priv->intstate = INTSTATE_IDLE;
+ return ret;
+}
+#endif
+
+/************************************************************************************
+ * Name: stm32_i2c_sem_waitstop
+ *
+ * Description:
+ * Wait for a STOP to complete
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv, int timeout_us)
+{
+ uint32_t start;
+ uint32_t elapsed;
+ uint32_t cr1;
+ uint32_t sr1;
+
+ /* Wait as stop might still be in progress; but stop might also
+ * be set because of a timeout error: "The [STOP] bit is set and
+ * cleared by software, cleared by hardware when a Stop condition is
+ * detected, set by hardware when a timeout error is detected."
+ */
+
+ start = clock_systimer();
+ do
+ {
+ /* Check for STOP condition */
+
+ cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
+ if ((cr1 & I2C_CR1_STOP) == 0)
+ {
+ return;
+ }
+
+ /* Check for timeout error */
+
+ sr1 = stm32_i2c_getreg(priv, STM32_I2C_SR1_OFFSET);
+ if ((sr1 & I2C_SR1_TIMEOUT) != 0)
+ {
+ return;
+ }
+
+ /* Calculate the elapsed time */
+
+ elapsed = clock_systimer() - start;
+ }
+
+ /* Loop until the stop is complete or a timeout occurs. */
+
+ while (elapsed < USEC2TICK(timeout_us));
+
+ /* If we get here then a timeout occurred with the STOP condition
+ * still pending.
+ */
+
+ i2cvdbg("Timeout with CR1: %04x SR1: %04x\n", cr1, sr1);
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_sem_post
+ *
+ * Description:
+ * Release the mutual exclusion semaphore
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_sem_post(FAR struct i2c_dev_s *dev)
+{
+ sem_post( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl );
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_sem_init
+ *
+ * Description:
+ * Initialize semaphores
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_sem_init(FAR struct i2c_dev_s *dev)
+{
+ sem_init(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl, 0, 1);
+#ifndef CONFIG_I2C_POLLED
+ sem_init(&((struct stm32_i2c_inst_s *)dev)->priv->sem_isr, 0, 0);
+#endif
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_sem_destroy
+ *
+ * Description:
+ * Destroy semaphores.
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_sem_destroy(FAR struct i2c_dev_s *dev)
+{
+ sem_destroy(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
+#ifndef CONFIG_I2C_POLLED
+ sem_destroy(&((struct stm32_i2c_inst_s *)dev)->priv->sem_isr);
+#endif
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_trace*
+ *
+ * Description:
+ * I2C trace instrumentation
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_I2C_TRACE
+static void stm32_i2c_traceclear(FAR struct stm32_i2c_priv_s *priv)
+{
+ struct stm32_trace_s *trace = &priv->trace[priv->tndx];
+
+ trace->status = 0; /* I2C 32-bit SR2|SR1 status */
+ trace->count = 0; /* Interrupt count when status change */
+ trace->event = I2CEVENT_NONE; /* Last event that occurred with this status */
+ trace->parm = 0; /* Parameter associated with the event */
+ trace->time = 0; /* Time of first status or event */
+}
+
+static void stm32_i2c_tracereset(FAR struct stm32_i2c_priv_s *priv)
+{
+ /* Reset the trace info for a new data collection */
+
+ priv->tndx = 0;
+ priv->start_time = clock_systimer();
+ stm32_i2c_traceclear(priv);
+}
+
+static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv, uint32_t status)
+{
+ struct stm32_trace_s *trace = &priv->trace[priv->tndx];
+
+ /* Is the current entry uninitialized? Has the status changed? */
+
+ if (trace->count == 0 || status != trace->status)
+ {
+ /* Yes.. Was it the status changed? */
+
+ if (trace->count != 0)
+ {
+ /* Yes.. bump up the trace index (unless we are out of trace entries) */
+
+ if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
+ {
+ i2cdbg("Trace table overflow\n");
+ return;
+ }
+
+ priv->tndx++;
+ trace = &priv->trace[priv->tndx];
+ }
+
+ /* Initialize the new trace entry */
+
+ stm32_i2c_traceclear(priv);
+ trace->status = status;
+ trace->count = 1;
+ trace->time = clock_systimer();
+ }
+ else
+ {
+ /* Just increment the count of times that we have seen this status */
+
+ trace->count++;
+ }
+}
+
+static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
+ enum stm32_trace_e event, uint32_t parm)
+{
+ struct stm32_trace_s *trace;
+
+ if (event != I2CEVENT_NONE)
+ {
+ trace = &priv->trace[priv->tndx];
+
+ /* Initialize the new trace entry */
+
+ trace->event = event;
+ trace->parm = parm;
+
+ /* Bump up the trace index (unless we are out of trace entries) */
+
+ if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
+ {
+ i2cdbg("Trace table overflow\n");
+ return;
+ }
+
+ priv->tndx++;
+ stm32_i2c_traceclear(priv);
+ }
+}
+
+static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv)
+{
+ struct stm32_trace_s *trace;
+ int i;
+
+ lib_rawprintf("Elapsed time: %d\n", clock_systimer() - priv->start_time);
+ for (i = 0; i <= priv->tndx; i++)
+ {
+ trace = &priv->trace[i];
+ lib_rawprintf("%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n",
+ i+1, trace->status, trace->count, trace->event, trace->parm,
+ trace->time - priv->start_time);
+ }
+}
+#endif /* CONFIG_I2C_TRACE */
+
+/************************************************************************************
+ * Name: stm32_i2c_setclock
+ *
+ * Description:
+ * Set the I2C clock
+ *
+ ************************************************************************************/
+
+static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequency)
+{
+ uint16_t cr1;
+ uint16_t ccr;
+ uint16_t trise;
+ uint16_t freqmhz;
+ uint16_t speed;
+
+ /* Disable the selected I2C peripheral to configure TRISE */
+
+ cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
+ stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1 & ~I2C_CR1_PE);
+
+ /* Update timing and control registers */
+
+ freqmhz = (uint16_t)(STM32_PCLK1_FREQUENCY / 1000000);
+ ccr = 0;
+
+ /* Configure speed in standard mode */
+
+ if (frequency <= 100000)
+ {
+ /* Standard mode speed calculation */
+
+ speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency << 1));
+
+ /* The CCR fault must be >= 4 */
+
+ if (speed < 4)
+ {
+ /* Set the minimum allowed value */
+
+ speed = 4;
+ }
+ ccr |= speed;
+
+ /* Set Maximum Rise Time for standard mode */
+
+ trise = freqmhz + 1;
+ }
+
+ /* Configure speed in fast mode */
+
+ else /* (frequency <= 400000) */
+ {
+ /* Fast mode speed calculation with Tlow/Thigh = 16/9 */
+
+#ifdef CONFIG_I2C_DUTY16_9
+ speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 25));
+
+ /* Set DUTY and fast speed bits */
+
+ ccr |= (I2C_CCR_DUTY|I2C_CCR_FS);
+#else
+ /* Fast mode speed calculation with Tlow/Thigh = 2 */
+
+ speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 3));
+
+ /* Set fast speed bit */
+
+ ccr |= I2C_CCR_FS;
+#endif
+
+ /* Verify that the CCR speed value is nonzero */
+
+ if (speed < 1)
+ {
+ /* Set the minimum allowed value */
+
+ speed = 1;
+ }
+ ccr |= speed;
+
+ /* Set Maximum Rise Time for fast mode */
+
+ trise = (uint16_t)(((freqmhz * 300) / 1000) + 1);
+ }
+
+ /* Write the new values of the CCR and TRISE registers */
+
+ stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, ccr);
+ stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, trise);
+
+ /* Bit 14 of OAR1 must be configured and kept at 1 */
+
+ stm32_i2c_putreg(priv, STM32_I2C_OAR1_OFFSET, I2C_OAR1_ONE);
+
+ /* Re-enable the peripheral (or not) */
+
+ stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_sendstart
+ *
+ * Description:
+ * Send the START conditions/force Master mode
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_sendstart(FAR struct stm32_i2c_priv_s *priv)
+{
+ /* Disable ACK on receive by default and generate START */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, I2C_CR1_START);
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_clrstart
+ *
+ * Description:
+ * Clear the STOP, START or PEC condition on certain error recovery steps.
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_clrstart(FAR struct stm32_i2c_priv_s *priv)
+{
+ /* "Note: When the STOP, START or PEC bit is set, the software must
+ * not perform any write access to I2C_CR1 before this bit is
+ * cleared by hardware. Otherwise there is a risk of setting a
+ * second STOP, START or PEC request."
+ *
+ * "The [STOP] bit is set and cleared by software, cleared by hardware
+ * when a Stop condition is detected, set by hardware when a timeout
+ * error is detected.
+ *
+ * "This [START] bit is set and cleared by software and cleared by hardware
+ * when start is sent or PE=0." The bit must be cleared by software if the
+ * START is never sent.
+ *
+ * "This [PEC] bit is set and cleared by software, and cleared by hardware
+ * when PEC is transferred or by a START or Stop condition or when PE=0."
+ */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET,
+ I2C_CR1_START|I2C_CR1_STOP|I2C_CR1_PEC, 0);
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_sendstop
+ *
+ * Description:
+ * Send the STOP conditions
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_sendstop(FAR struct stm32_i2c_priv_s *priv)
+{
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, I2C_CR1_STOP);
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_getstatus
+ *
+ * Description:
+ * Get 32-bit status (SR1 and SR2 combined)
+ *
+ ************************************************************************************/
+
+static inline uint32_t stm32_i2c_getstatus(FAR struct stm32_i2c_priv_s *priv)
+{
+ uint32_t status = stm32_i2c_getreg(priv, STM32_I2C_SR1_OFFSET);
+ status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);
+ return status;
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_disablefsmc
+ *
+ * Description:
+ * FSMC must be disable while accessing I2C1 because it uses a common resource
+ * (LBAR)
+ *
+ * NOTE: This is an issue with the STM32F103ZE, but may not be an issue with other
+ * STM32s. You may need to experiment
+ *
+ ************************************************************************************/
+
+#ifdef I2C1_FSMC_CONFLICT
+static inline uint32_t stm32_i2c_disablefsmc(FAR struct stm32_i2c_priv_s *priv)
+{
+ uint32_t ret = 0;
+ uint32_t regval;
+
+ /* Is this I2C1 */
+
+#ifdef CONFIG_STM32_I2C2
+ if (priv->base == STM32_I2C1_BASE)
+#endif
+ {
+ /* Disable FSMC unconditionally */
+
+ ret = getreg32( STM32_RCC_AHBENR);
+ regval = ret & ~RCC_AHBENR_FSMCEN;
+ putreg32(regval, STM32_RCC_AHBENR);
+ }
+ return ret;
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_enablefsmc
+ *
+ * Description:
+ * Re-enabled the FSMC
+ *
+ ************************************************************************************/
+
+static inline void stm32_i2c_enablefsmc(uint32_t ahbenr)
+{
+ uint32_t regval;
+
+ /* Enable AHB clocking to the FSMC only if it was previously enabled. */
+
+ if ((ahbenr & RCC_AHBENR_FSMCEN) != 0)
+ {
+ regval = getreg32( STM32_RCC_AHBENR);
+ regval |= RCC_AHBENR_FSMCEN;
+ putreg32(regval, STM32_RCC_AHBENR);
+ }
+}
+#else
+# define stm32_i2c_disablefsmc(priv) (0)
+# define stm32_i2c_enablefsmc(ahbenr)
+#endif /* I2C1_FSMC_CONFLICT */
+
+/************************************************************************************
+ * Name: stm32_i2c_isr
+ *
+ * Description:
+ * Common Interrupt Service Routine
+ *
+ ************************************************************************************/
+
+static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
+{
+ uint32_t status = stm32_i2c_getstatus(priv);
+
+ /* Check for new trace setup */
+
+ stm32_i2c_tracenew(priv, status);
+
+ /* Was start bit sent */
+
+ if ((status & I2C_SR1_SB) != 0)
+ {
+ stm32_i2c_traceevent(priv, I2CEVENT_SENDADDR, priv->msgc);
+
+ /* Get run-time data */
+
+ priv->ptr = priv->msgv->buffer;
+ priv->dcnt = priv->msgv->length;
+ priv->flags = priv->msgv->flags;
+
+ /* Send address byte and define addressing mode */
+
+ stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET,
+ (priv->flags & I2C_M_TEN) ?
+ 0 : ((priv->msgv->addr << 1) | (priv->flags & I2C_M_READ)));
+
+ /* Set ACK for receive mode */
+
+ if (priv->dcnt > 1 && (priv->flags & I2C_M_READ) != 0)
+ {
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, 0, I2C_CR1_ACK);
+ }
+
+ /* Increment to next pointer and decrement message count */
+
+ priv->msgv++;
+ priv->msgc--;
+ }
+
+ /* In 10-bit addressing mode, was first byte sent */
+
+ else if ((status & I2C_SR1_ADD10) != 0)
+ {
+ /* TODO: Finish 10-bit mode addressing */
+ }
+
+ /* Was address sent, continue with either sending or reading data */
+
+ else if ((priv->flags & I2C_M_READ) == 0 && (status & (I2C_SR1_ADDR | I2C_SR1_TXE)) != 0)
+ {
+ if (priv->dcnt > 0)
+ {
+ /* Send a byte */
+
+ stm32_i2c_traceevent(priv, I2CEVENT_SENDBYTE, priv->dcnt);
+ stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, *priv->ptr++);
+ priv->dcnt--;
+ }
+ }
+
+ else if ((priv->flags & I2C_M_READ) != 0 && (status & I2C_SR1_ADDR) != 0)
+ {
+ /* Enable RxNE and TxE buffers in order to receive one or multiple bytes */
+
+#ifndef CONFIG_I2C_POLLED
+ stm32_i2c_traceevent(priv, I2CEVENT_ITBUFEN, 0);
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN);
+#endif
+ }
+
+ /* More bytes to read */
+
+ else if ((status & I2C_SR1_RXNE) != 0)
+ {
+ /* Read a byte, if dcnt goes < 0, then read dummy bytes to ack ISRs */
+
+ if (priv->dcnt > 0)
+ {
+ stm32_i2c_traceevent(priv, I2CEVENT_RCVBYTE, priv->dcnt);
+
+ /* Receive a byte */
+
+ *priv->ptr++ = stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
+
+ /* Disable acknowledge when last byte is to be received */
+
+ if (priv->dcnt == 1)
+ {
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 0);
+ }
+ priv->dcnt--;
+ }
+ }
+
+ /* Do we have more bytes to send, enable/disable buffer interrupts
+ * (these ISRs could be replaced by DMAs)
+ */
+
+#ifndef CONFIG_I2C_POLLED
+ if (priv->dcnt > 0)
+ {
+ stm32_i2c_traceevent(priv, I2CEVENT_REITBUFEN, 0);
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN);
+ }
+ else if (priv->dcnt == 0)
+ {
+ stm32_i2c_traceevent(priv, I2CEVENT_DISITBUFEN, 0);
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_ITBUFEN, 0);
+ }
+#endif
+
+ /* Was last byte received or sent? Hmmm... the F2 and F4 seems to differ from
+ * the F1 in that BTF is not set after data is received (only RXNE).
+ */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ if (priv->dcnt <= 0 && (status & (I2C_SR1_BTF|I2C_SR1_RXNE)) != 0)
+#else
+ if (priv->dcnt <= 0 && (status & I2C_SR1_BTF) != 0)
+#endif
+ {
+ stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET); /* ACK ISR */
+
+ /* Do we need to terminate or restart after this byte?
+ * If there are more messages to send, then we may:
+ *
+ * - continue with repeated start
+ * - or just continue sending writeable part
+ * - or we close down by sending the stop bit
+ */
+
+ if (priv->msgc > 0)
+ {
+ if (priv->msgv->flags & I2C_M_NORESTART)
+ {
+ stm32_i2c_traceevent(priv, I2CEVENT_BTFNOSTART, priv->msgc);
+ priv->ptr = priv->msgv->buffer;
+ priv->dcnt = priv->msgv->length;
+ priv->flags = priv->msgv->flags;
+ priv->msgv++;
+ priv->msgc--;
+
+ /* Restart this ISR! */
+
+#ifndef CONFIG_I2C_POLLED
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN);
+#endif
+ }
+ else
+ {
+ stm32_i2c_traceevent(priv, I2CEVENT_BTFRESTART, priv->msgc);
+ stm32_i2c_sendstart(priv);
+ }
+ }
+ else if (priv->msgv)
+ {
+ stm32_i2c_traceevent(priv, I2CEVENT_BTFSTOP, 0);
+ stm32_i2c_sendstop(priv);
+
+ /* Is there a thread waiting for this event (there should be) */
+
+#ifndef CONFIG_I2C_POLLED
+ if (priv->intstate == INTSTATE_WAITING)
+ {
+ /* Yes.. inform the thread that the transfer is complete
+ * and wake it up.
+ */
+
+ sem_post( &priv->sem_isr );
+ priv->intstate = INTSTATE_DONE;
+ }
+#else
+ priv->intstate = INTSTATE_DONE;
+#endif
+
+ /* Mark that we have stopped with this transaction */
+
+ priv->msgv = NULL;
+ }
+ }
+
+ /* Check for errors, in which case, stop the transfer and return
+ * Note that in master reception mode AF becomes set on last byte
+ * since ACK is not returned. We should ignore this error.
+ */
+
+ if ((status & I2C_SR1_ERRORMASK) != 0)
+ {
+ stm32_i2c_traceevent(priv, I2CEVENT_ERROR, 0);
+
+ /* Clear interrupt flags */
+
+ stm32_i2c_putreg(priv, STM32_I2C_SR1_OFFSET, 0);
+
+ /* Is there a thread waiting for this event (there should be) */
+
+#ifndef CONFIG_I2C_POLLED
+ if (priv->intstate == INTSTATE_WAITING)
+ {
+ /* Yes.. inform the thread that the transfer is complete
+ * and wake it up.
+ */
+
+ sem_post( &priv->sem_isr );
+ priv->intstate = INTSTATE_DONE;
+ }
+#else
+ priv->intstate = INTSTATE_DONE;
+#endif
+ }
+
+ priv->status = status;
+ return OK;
+}
+
+/************************************************************************************
+ * Name: stm32_i2c1_isr
+ *
+ * Description:
+ * I2C1 interrupt service routine
+ *
+ ************************************************************************************/
+
+#ifndef CONFIG_I2C_POLLED
+#ifdef CONFIG_STM32_I2C1
+static int stm32_i2c1_isr(int irq, void *context)
+{
+ return stm32_i2c_isr(&stm32_i2c1_priv);
+}
+#endif
+
+/************************************************************************************
+ * Name: stm32_i2c2_isr
+ *
+ * Description:
+ * I2C2 interrupt service routine
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_I2C2
+static int stm32_i2c2_isr(int irq, void *context)
+{
+ return stm32_i2c_isr(&stm32_i2c2_priv);
+}
+#endif
+
+/************************************************************************************
+ * Name: stm32_i2c3_isr
+ *
+ * Description:
+ * I2C2 interrupt service routine
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_I2C3
+static int stm32_i2c3_isr(int irq, void *context)
+{
+ return stm32_i2c_isr(&stm32_i2c3_priv);
+}
+#endif
+#endif
+
+/************************************************************************************
+ * Private Initialization and Deinitialization
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_i2c_init
+ *
+ * Description:
+ * Setup the I2C hardware, ready for operation with defaults
+ *
+ ************************************************************************************/
+
+static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
+{
+ /* Power-up and configure GPIOs */
+
+ switch (priv->base)
+ {
+#ifdef CONFIG_STM32_I2C1
+ case STM32_I2C1_BASE:
+
+ /* Enable power and reset the peripheral */
+
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C1EN);
+
+ modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C1RST);
+ modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST, 0);
+
+ /* Configure pins */
+
+ if (stm32_configgpio(GPIO_I2C1_SCL) < 0)
+ {
+ return ERROR;
+ }
+
+ if (stm32_configgpio(GPIO_I2C1_SDA) < 0)
+ {
+ stm32_unconfiggpio(GPIO_I2C1_SCL);
+ return ERROR;
+ }
+
+ /* Attach ISRs */
+
+#ifndef CONFIG_I2C_POLLED
+ irq_attach(STM32_IRQ_I2C1EV, stm32_i2c1_isr);
+ irq_attach(STM32_IRQ_I2C1ER, stm32_i2c1_isr);
+ up_enable_irq(STM32_IRQ_I2C1EV);
+ up_enable_irq(STM32_IRQ_I2C1ER);
+#endif
+ break;
+#endif
+
+#ifdef CONFIG_STM32_I2C2
+ case STM32_I2C2_BASE:
+
+ /* Enable power and reset the peripheral */
+
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C2EN);
+
+ modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C2RST);
+ modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST, 0);
+
+ /* Configure pins */
+
+ if (stm32_configgpio(GPIO_I2C2_SCL) < 0)
+ {
+ return ERROR;
+ }
+
+ if (stm32_configgpio(GPIO_I2C2_SDA) < 0)
+ {
+ stm32_unconfiggpio(GPIO_I2C2_SCL);
+ return ERROR;
+ }
+
+ /* Attach ISRs */
+
+#ifndef CONFIG_I2C_POLLED
+ irq_attach(STM32_IRQ_I2C2EV, stm32_i2c2_isr);
+ irq_attach(STM32_IRQ_I2C2ER, stm32_i2c2_isr);
+ up_enable_irq(STM32_IRQ_I2C2EV);
+ up_enable_irq(STM32_IRQ_I2C2ER);
+#endif
+ break;
+#endif
+
+#ifdef CONFIG_STM32_I2C3
+ case STM32_I2C3_BASE:
+
+ /* Enable power and reset the peripheral */
+
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C3EN);
+
+ modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C3RST);
+ modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C3RST, 0);
+
+ /* Configure pins */
+
+ if (stm32_configgpio(GPIO_I2C3_SCL) < 0)
+ {
+ return ERROR;
+ }
+
+ if (stm32_configgpio(GPIO_I2C3_SDA) < 0)
+ {
+ stm32_unconfiggpio(GPIO_I2C3_SCL);
+ return ERROR;
+ }
+
+ /* Attach ISRs */
+
+#ifndef CONFIG_I2C_POLLED
+ irq_attach(STM32_IRQ_I2C3EV, stm32_i2c3_isr);
+ irq_attach(STM32_IRQ_I2C3ER, stm32_i2c3_isr);
+ up_enable_irq(STM32_IRQ_I2C3EV);
+ up_enable_irq(STM32_IRQ_I2C3ER);
+#endif
+ break;
+#endif
+
+ default:
+ return ERROR;
+ }
+
+ /* Set peripheral frequency, where it must be at least 2 MHz for 100 kHz
+ * or 4 MHz for 400 kHz. This also disables all I2C interrupts.
+ */
+
+ stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, (STM32_PCLK1_FREQUENCY / 1000000));
+ stm32_i2c_setclock(priv, 100000);
+
+ /* Enable I2C */
+
+ stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_PE);
+ return OK;
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_deinit
+ *
+ * Description:
+ * Shutdown the I2C hardware
+ *
+ ************************************************************************************/
+
+static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
+{
+ /* Disable I2C */
+
+ stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, 0);
+
+ switch (priv->base)
+ {
+#ifdef CONFIG_STM32_I2C1
+ case STM32_I2C1_BASE:
+ stm32_unconfiggpio(GPIO_I2C1_SCL);
+ stm32_unconfiggpio(GPIO_I2C1_SDA);
+
+#ifndef CONFIG_I2C_POLLED
+ up_disable_irq(STM32_IRQ_I2C1EV);
+ up_disable_irq(STM32_IRQ_I2C1ER);
+ irq_detach(STM32_IRQ_I2C1EV);
+ irq_detach(STM32_IRQ_I2C1ER);
+#endif
+ modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_I2C1EN, 0);
+ break;
+#endif
+
+#ifdef CONFIG_STM32_I2C2
+ case STM32_I2C2_BASE:
+ stm32_unconfiggpio(GPIO_I2C2_SCL);
+ stm32_unconfiggpio(GPIO_I2C2_SDA);
+
+#ifndef CONFIG_I2C_POLLED
+ up_disable_irq(STM32_IRQ_I2C2EV);
+ up_disable_irq(STM32_IRQ_I2C2ER);
+ irq_detach(STM32_IRQ_I2C2EV);
+ irq_detach(STM32_IRQ_I2C2ER);
+#endif
+ modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_I2C2EN, 0);
+ break;
+#endif
+
+#ifdef CONFIG_STM32_I2C3
+ case STM32_I2C3_BASE:
+ stm32_unconfiggpio(GPIO_I2C3_SCL);
+ stm32_unconfiggpio(GPIO_I2C3_SDA);
+
+#ifndef CONFIG_I2C_POLLED
+ up_disable_irq(STM32_IRQ_I2C3EV);
+ up_disable_irq(STM32_IRQ_I2C3ER);
+ irq_detach(STM32_IRQ_I2C3EV);
+ irq_detach(STM32_IRQ_I2C3ER);
+#endif
+ modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_I2C3EN, 0);
+ break;
+#endif
+
+ default:
+ return ERROR;
+ }
+
+ return OK;
+}
+
+/************************************************************************************
+ * Device Driver Operations
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_i2c_setfrequency
+ *
+ * Description:
+ * Set the I2C frequency
+ *
+ ************************************************************************************/
+
+static uint32_t stm32_i2c_setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency)
+{
+ stm32_i2c_sem_wait(dev);
+
+#if STM32_PCLK1_FREQUENCY < 4000000
+ ((struct stm32_i2c_inst_s *)dev)->frequency = 100000;
+#else
+ ((struct stm32_i2c_inst_s *)dev)->frequency = frequency;
+#endif
+
+ stm32_i2c_sem_post(dev);
+ return ((struct stm32_i2c_inst_s *)dev)->frequency;
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_setaddress
+ *
+ * Description:
+ * Set the I2C slave address
+ *
+ ************************************************************************************/
+
+static int stm32_i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits)
+{
+ stm32_i2c_sem_wait(dev);
+
+ ((struct stm32_i2c_inst_s *)dev)->address = addr;
+ ((struct stm32_i2c_inst_s *)dev)->flags = (nbits == 10) ? I2C_M_TEN : 0;
+
+ stm32_i2c_sem_post(dev);
+ return OK;
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_process
+ *
+ * Description:
+ * Common I2C transfer logic
+ *
+ ************************************************************************************/
+
+static int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int count)
+{
+ struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
+ FAR struct stm32_i2c_priv_s *priv = inst->priv;
+ uint32_t status = 0;
+ //uint32_t ahbenr;
+ int errval = 0;
+
+ ASSERT(count);
+
+ /* Disable FSMC that shares a pin with I2C1 (LBAR) */
+
+ (void)stm32_i2c_disablefsmc(priv);
+
+ /* Wait for any STOP in progress. NOTE: If we have to disable the FSMC
+ * then we cannot do this at the top of the loop, unfortunately. The STOP
+ * will not complete normally if the FSMC is enabled.
+ */
+
+#ifndef I2C1_FSMC_CONFLICT
+ #if CONFIG_STM32_I2CTIMEOUS_START_STOP > 0
+ stm32_i2c_sem_waitstop(priv, CONFIG_STM32_I2CTIMEOUS_START_STOP);
+ #else
+ stm32_i2c_sem_waitstop(priv, CONFIG_STM32_I2CTIMEOMS + CONFIG_STM32_I2CTIMEOSEC * 1000000);
+ #endif
+#endif
+
+ /* Clear any pending error interrupts */
+
+ stm32_i2c_putreg(priv, STM32_I2C_SR1_OFFSET, 0);
+
+ /* "Note: When the STOP, START or PEC bit is set, the software must
+ * not perform any write access to I2C_CR1 before this bit is
+ * cleared by hardware. Otherwise there is a risk of setting a
+ * second STOP, START or PEC request." However, if the bits are
+ * not cleared by hardware, then we will have to do that from hardware.
+ */
+
+ stm32_i2c_clrstart(priv);
+
+ /* Old transfers are done */
+
+ priv->msgv = msgs;
+ priv->msgc = count;
+
+ /* Calculate timeout values */
+ int timeout_us = 0;
+ #if CONFIG_STM32_I2CTIMEOUS_PER_BYTE > 0
+ /* Count the number of bytes left to process */
+ int i;
+ int bytecount = 10;
+ for (i = 0; i < count; i++)
+ {
+ bytecount += msgs[i].length;
+ }
+ timeout_us = CONFIG_STM32_I2CTIMEOUS_PER_BYTE * bytecount;
+ //i2cvdbg("i2c wait: %d\n", timeout_us);
+ #else
+ timeout_us = CONFIG_STM32_I2CTIMEOMS + CONFIG_STM32_I2CTIMEOSEC * 1000000;
+ #endif
+
+ /* Reset I2C trace logic */
+
+ stm32_i2c_tracereset(priv);
+
+ /* Set I2C clock frequency (on change it toggles I2C_CR1_PE !) */
+
+ stm32_i2c_setclock(priv, inst->frequency);
+
+ /* Trigger start condition, then the process moves into the ISR. I2C
+ * interrupts will be enabled within stm32_i2c_waitdone().
+ */
+
+ priv->status = 0;
+ stm32_i2c_sendstart(priv);
+
+ /* Wait for an ISR, if there was a timeout, fetch latest status to get
+ * the BUSY flag.
+ */
+
+ if (stm32_i2c_sem_waitdone(priv, timeout_us) < 0)
+ {
+ status = stm32_i2c_getstatus(priv);
+ errval = ETIMEDOUT;
+
+ i2cdbg("Timed out: CR1: %04x status: %08x\n",
+ stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET), status);
+
+ /* "Note: When the STOP, START or PEC bit is set, the software must
+ * not perform any write access to I2C_CR1 before this bit is
+ * cleared by hardware. Otherwise there is a risk of setting a
+ * second STOP, START or PEC request."
+ */
+
+ stm32_i2c_clrstart(priv);
+ // XXX also clear busy flag in case of timeout
+ status = priv->status & 0xffff;
+ }
+ else
+ {
+ /* clear SR2 (BUSY flag) as we've done successfully */
+
+ status = priv->status & 0xffff;
+ }
+
+ /* Check for error status conditions */
+
+ if ((status & I2C_SR1_ERRORMASK) != 0)
+ {
+ /* I2C_SR1_ERRORMASK is the 'OR' of the following individual bits: */
+
+ if (status & I2C_SR1_BERR)
+ {
+ /* Bus Error */
+
+ errval = EIO;
+ }
+ else if (status & I2C_SR1_ARLO)
+ {
+ /* Arbitration Lost (master mode) */
+
+ errval = EAGAIN;
+ }
+ else if (status & I2C_SR1_AF)
+ {
+ /* Acknowledge Failure */
+
+ errval = ENXIO;
+ }
+ else if (status & I2C_SR1_OVR)
+ {
+ /* Overrun/Underrun */
+
+ errval = EIO;
+ }
+ else if (status & I2C_SR1_PECERR)
+ {
+ /* PEC Error in reception */
+
+ errval = EPROTO;
+ }
+ else if (status & I2C_SR1_TIMEOUT)
+ {
+ /* Timeout or Tlow Error */
+
+ errval = ETIME;
+ }
+
+ /* This is not an error and should never happen since SMBus is not enabled */
+
+ else /* if (status & I2C_SR1_SMBALERT) */
+ {
+ /* SMBus alert is an optional signal with an interrupt line for devices
+ * that want to trade their ability to master for a pin.
+ */
+
+ errval = EINTR;
+ }
+ }
+
+ /* This is not an error, but should not happen. The BUSY signal can hang,
+ * however, if there are unhealthy devices on the bus that need to be reset.
+ * NOTE: We will only see this buy indication if stm32_i2c_sem_waitdone()
+ * fails above; Otherwise it is cleared.
+ */
+
+ else if ((status & (I2C_SR2_BUSY << 16)) != 0)
+ {
+ /* I2C Bus is for some reason busy */
+
+ errval = EBUSY;
+ }
+
+ /* Dump the trace result */
+
+ stm32_i2c_tracedump(priv);
+
+ /* Wait for any STOP in progress. NOTE: If we have to disable the FSMC
+ * then we cannot do this at the top of the loop, unfortunately. The STOP
+ * will not complete normally if the FSMC is enabled.
+ */
+
+#ifdef I2C1_FSMC_CONFLICT
+ stm32_i2c_sem_waitstop(priv);
+#endif
+
+ /* Re-enable the FSMC */
+
+ stm32_i2c_enablefsmc(ahbenr);
+ stm32_i2c_sem_post(dev);
+
+ return -errval;
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_write
+ *
+ * Description:
+ * Write I2C data
+ *
+ ************************************************************************************/
+
+static int stm32_i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen)
+{
+ stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
+
+ struct i2c_msg_s msgv =
+ {
+ .addr = ((struct stm32_i2c_inst_s *)dev)->address,
+ .flags = ((struct stm32_i2c_inst_s *)dev)->flags,
+ .buffer = (uint8_t *)buffer,
+ .length = buflen
+ };
+
+ return stm32_i2c_process(dev, &msgv, 1);
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_read
+ *
+ * Description:
+ * Read I2C data
+ *
+ ************************************************************************************/
+
+int stm32_i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen)
+{
+ stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
+
+ struct i2c_msg_s msgv =
+ {
+ .addr = ((struct stm32_i2c_inst_s *)dev)->address,
+ .flags = ((struct stm32_i2c_inst_s *)dev)->flags | I2C_M_READ,
+ .buffer = buffer,
+ .length = buflen
+ };
+
+ return stm32_i2c_process(dev, &msgv, 1);
+}
+
+/************************************************************************************
+ * Name: stm32_i2c_writeread
+ *
+ * Description:
+ * Read then write I2C data
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_I2C_WRITEREAD
+static int stm32_i2c_writeread(FAR struct i2c_dev_s *dev,
+ const uint8_t *wbuffer, int wbuflen,
+ uint8_t *buffer, int buflen)
+{
+ stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
+
+ struct i2c_msg_s msgv[2] =
+ {
+ {
+ .addr = ((struct stm32_i2c_inst_s *)dev)->address,
+ .flags = ((struct stm32_i2c_inst_s *)dev)->flags,
+ .buffer = (uint8_t *)wbuffer, /* this is really ugly, sorry const ... */
+ .length = wbuflen
+ },
+ {
+ .addr = ((struct stm32_i2c_inst_s *)dev)->address,
+ .flags = ((struct stm32_i2c_inst_s *)dev)->flags | ((buflen>0) ? I2C_M_READ : I2C_M_NORESTART),
+ .buffer = buffer,
+ .length = (buflen>0) ? buflen : -buflen
+ }
+ };
+
+ return stm32_i2c_process(dev, msgv, 2);
+}
+#endif
+
+/************************************************************************************
+ * Name: stm32_i2c_transfer
+ *
+ * Description:
+ * Generic I2C transfer function
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_I2C_TRANSFER
+static int stm32_i2c_transfer(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs,
+ int count)
+{
+ stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
+ return stm32_i2c_process(dev, msgs, count);
+}
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_i2cinitialize
+ *
+ * Description:
+ * Initialize one I2C bus
+ *
+ ************************************************************************************/
+
+FAR struct i2c_dev_s *up_i2cinitialize(int port)
+{
+ struct stm32_i2c_priv_s * priv = NULL; /* private data of device with multiple instances */
+ struct stm32_i2c_inst_s * inst = NULL; /* device, single instance */
+ int irqs;
+
+#if STM32_PCLK1_FREQUENCY < 4000000
+# warning STM32_I2C_INIT: Peripheral clock must be at least 4 MHz to support 400 kHz operation.
+#endif
+
+#if STM32_PCLK1_FREQUENCY < 2000000
+# warning STM32_I2C_INIT: Peripheral clock must be at least 2 MHz to support 100 kHz operation.
+ return NULL;
+#endif
+
+ /* Get I2C private structure */
+
+ switch (port)
+ {
+#ifdef CONFIG_STM32_I2C1
+ case 1:
+ priv = (struct stm32_i2c_priv_s *)&stm32_i2c1_priv;
+ break;
+#endif
+#ifdef CONFIG_STM32_I2C2
+ case 2:
+ priv = (struct stm32_i2c_priv_s *)&stm32_i2c2_priv;
+ break;
+#endif
+#ifdef CONFIG_STM32_I2C3
+ case 3:
+ priv = (struct stm32_i2c_priv_s *)&stm32_i2c3_priv;
+ break;
+#endif
+ default:
+ return NULL;
+ }
+
+ /* Allocate instance */
+
+ if (!(inst = kmalloc( sizeof(struct stm32_i2c_inst_s))))
+ {
+ return NULL;
+ }
+
+ /* Initialize instance */
+
+ inst->ops = &stm32_i2c_ops;
+ inst->priv = priv;
+ inst->frequency = 100000;
+ inst->address = 0;
+ inst->flags = 0;
+
+ /* Init private data for the first time, increment refs count,
+ * power-up hardware and configure GPIOs.
+ */
+
+ irqs = irqsave();
+
+ if ((volatile int)priv->refs++ == 0)
+ {
+ stm32_i2c_sem_init( (struct i2c_dev_s *)inst );
+ stm32_i2c_init( priv );
+ }
+
+ irqrestore(irqs);
+ return (struct i2c_dev_s *)inst;
+}
+
+/************************************************************************************
+ * Name: up_i2cuninitialize
+ *
+ * Description:
+ * Uninitialize an I2C bus
+ *
+ ************************************************************************************/
+
+int up_i2cuninitialize(FAR struct i2c_dev_s * dev)
+{
+ int irqs;
+
+ ASSERT(dev);
+
+ /* Decrement refs and check for underflow */
+
+ if (((struct stm32_i2c_inst_s *)dev)->priv->refs == 0)
+ {
+ return ERROR;
+ }
+
+ irqs = irqsave();
+
+ if (--((struct stm32_i2c_inst_s *)dev)->priv->refs)
+ {
+ irqrestore(irqs);
+ kfree(dev);
+ return OK;
+ }
+
+ irqrestore(irqs);
+
+ /* Disable power and other HW resource (GPIO's) */
+
+ stm32_i2c_deinit( ((struct stm32_i2c_inst_s *)dev)->priv );
+
+ /* Release unused resources */
+
+ stm32_i2c_sem_destroy( (struct i2c_dev_s *)dev );
+
+ kfree(dev);
+ return OK;
+}
+
+/************************************************************************************
+ * Name: up_i2creset
+ *
+ * Description:
+ * Reset an I2C bus
+ *
+ ************************************************************************************/
+
+int up_i2creset(FAR struct i2c_dev_s * dev)
+{
+ // ASSERT(dev);
+
+ // stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
+
+ // struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
+ // FAR struct stm32_i2c_priv_s *priv = inst->priv;
+
+ // /* Clear any pending error interrupts */
+
+ // stm32_i2c_putreg(priv, STM32_I2C_SR1_OFFSET, 0);
+
+ // /* "Note: When the STOP, START or PEC bit is set, the software must
+ // * not perform any write access to I2C_CR1 before this bit is
+ // * cleared by hardware. Otherwise there is a risk of setting a
+ // * second STOP, START or PEC request." However, if the bits are
+ // * not cleared by hardware, then we will have to do that from hardware.
+ // */
+
+ // stm32_i2c_clrstart(priv);
+
+ // /* Reset peripheral */
+ // uint16_t cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
+ // /* Set reset flag */
+ // cr1 &= I2C_CR1_SWRST;
+ // stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
+ // /* Clear CR1 */
+ // stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, 0);
+
+ // switch (priv->base)
+ // {
+ // case STM32_I2C1_BASE:
+ // modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C1RST);
+ // modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST, 0);
+ // break;
+ // case STM32_I2C2_BASE:
+ // modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C2RST);
+ // modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST, 0);
+ // break;
+ // case STM32_I2C3_BASE:
+ // modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C3RST);
+ // modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C3RST, 0);
+ // break;
+ // }
+
+
+
+ // stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, (STM32_PCLK1_FREQUENCY / 1000000));
+ // stm32_i2c_setclock(priv, inst->frequency);
+ // inst->flags = 0;
+
+ // /* Enable I2C */
+
+ // stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_PE);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ int irqs;
+
+ ASSERT(dev);
+
+ /* Decrement refs and check for underflow */
+
+ if (((struct stm32_i2c_inst_s *)dev)->priv->refs == 0)
+ {
+ return ERROR;
+ }
+
+ irqs = irqsave();
+
+ irqrestore(irqs);
+
+ /* Disable power and other HW resource (GPIO's) */
+
+ //stm32_i2c_deinit( ((struct stm32_i2c_inst_s *)dev)->priv );
+
+ /* Release unused resources */
+
+ //stm32_i2c_sem_destroy( (struct i2c_dev_s *)dev );
+
+ struct stm32_i2c_priv_s * priv = NULL; /* private data of device with multiple instances */
+ struct stm32_i2c_inst_s * inst = NULL; /* device, single instance */
+
+#if STM32_PCLK1_FREQUENCY < 4000000
+# warning STM32_I2C_INIT: Peripheral clock must be at least 4 MHz to support 400 kHz operation.
+#endif
+
+#if STM32_PCLK1_FREQUENCY < 2000000
+# warning STM32_I2C_INIT: Peripheral clock must be at least 2 MHz to support 100 kHz operation.
+ return NULL;
+#endif
+
+ /* Get I2C private structure */
+
+ priv = ((struct stm32_i2c_inst_s *)dev)->priv;
+
+// switch (port)
+// {
+// #ifdef CONFIG_STM32_I2C1
+// case 1:
+// priv = (struct stm32_i2c_priv_s *)&stm32_i2c1_priv;
+// break;
+// #endif
+// #ifdef CONFIG_STM32_I2C2
+// case 2:
+// priv = (struct stm32_i2c_priv_s *)&stm32_i2c2_priv;
+// break;
+// #endif
+// #ifdef CONFIG_STM32_I2C3
+// case 3:
+// priv = (struct stm32_i2c_priv_s *)&stm32_i2c3_priv;
+// break;
+// #endif
+// default:
+// return NULL;
+// }
+
+ /* Allocate instance */
+ inst = (struct stm32_i2c_inst_s *)dev;
+
+ /* Initialize instance */
+
+ inst->ops = &stm32_i2c_ops;
+ inst->priv = priv;
+ inst->frequency = 100000;
+ inst->address = 0;
+ inst->flags = 0;
+
+ /* Init private data for the first time, increment refs count,
+ * power-up hardware and configure GPIOs.
+ */
+
+ irqs = irqsave();
+
+ if ((volatile int)priv->refs++ == 0)
+ {
+ stm32_i2c_sem_init( (struct i2c_dev_s *)inst );
+ stm32_i2c_init( priv );
+ }
+
+ irqrestore(irqs);
+ return OK;
+}
+
+#endif /* defined(CONFIG_STM32_I2C1) && defined(CONFIG_STM32_I2C2) */
diff --git a/nuttx/arch/arm/src/stm32/stm32_i2c.h b/nuttx/arch/arm/src/stm32/stm32_i2c.h
new file mode 100644
index 000000000..23a06bc05
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_i2c.h
@@ -0,0 +1,50 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_i2c.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_STM32_I2C_H
+#define __ARCH_ARM_SRC_STM32_STM32_I2C_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/i2c.h>
+
+#include "chip.h"
+#include "chip/stm32_i2c.h"
+
+#endif /* __ARCH_ARM_SRC_STM32_STM32_I2C_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_idle.c b/nuttx/arch/arm/src/stm32/stm32_idle.c
new file mode 100644
index 000000000..791a79429
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_idle.c
@@ -0,0 +1,188 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_idle.c
+ *
+ * Copyright (C) 2011-2012 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 <arch/board/board.h>
+#include <nuttx/config.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/power/pm.h>
+
+#include <arch/irq.h>
+
+#include "stm32_pm.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Does the board support an IDLE LED to indicate that the board is in the
+ * IDLE state?
+ */
+
+#if defined(CONFIG_ARCH_LEDS) && defined(LED_IDLE)
+# define BEGIN_IDLE() up_ledon(LED_IDLE)
+# define END_IDLE() up_ledoff(LED_IDLE)
+#else
+# define BEGIN_IDLE()
+# define END_IDLE()
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_idlepm
+ *
+ * Description:
+ * Perform IDLE state power management.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static void up_idlepm(void)
+{
+ static enum pm_state_e oldstate = PM_NORMAL;
+ enum pm_state_e newstate;
+ irqstate_t flags;
+ int ret;
+
+ /* Decide, which power saving level can be obtained */
+
+ newstate = pm_checkstate();
+
+ /* Check for state changes */
+
+ if (newstate != oldstate)
+ {
+ flags = irqsave();
+
+ /* Perform board-specific, state-dependent logic here */
+
+ llvdbg("newstate= %d oldstate=%d\n", newstate, oldstate);
+
+ /* Then force the global state change */
+
+ ret = pm_changestate(newstate);
+ if (ret < 0)
+ {
+ /* The new state change failed, revert to the preceding state */
+
+ (void)pm_changestate(oldstate);
+ }
+ else
+ {
+ /* Save the new state */
+
+ oldstate = newstate;
+ }
+
+ /* MCU-specific power management logic */
+
+ switch (newstate)
+ {
+ case PM_NORMAL:
+ break;
+
+ case PM_IDLE:
+ break;
+
+ case PM_STANDBY:
+ stm32_pmstop(true);
+ break;
+
+ case PM_SLEEP:
+ (void)stm32_pmstandby();
+ break;
+
+ default:
+ break;
+ }
+
+ irqrestore(flags);
+ }
+}
+#else
+# define up_idlepm()
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_idle
+ *
+ * Description:
+ * up_idle() is the logic that will be executed when their is no other
+ * ready-to-run task. This is processor idle time and will continue until
+ * some interrupt occurs to cause a context switch from the idle task.
+ *
+ * Processing in this state may be processor-specific. e.g., this is where
+ * power management operations might be performed.
+ *
+ ****************************************************************************/
+
+void up_idle(void)
+{
+#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS)
+ /* If the system is idle and there are no timer interrupts, then process
+ * "fake" timer interrupts. Hopefully, something will wake up.
+ */
+
+ sched_process_timer();
+#else
+
+ /* Perform IDLE mode power management */
+
+ up_idlepm();
+
+ /* Sleep until an interrupt occurs to save power */
+
+ BEGIN_IDLE();
+ asm("WFI");
+ END_IDLE();
+#endif
+}
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_internal.h b/nuttx/arch/arm/src/stm32/stm32_internal.h
new file mode 100644
index 000000000..8db936786
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_internal.h
@@ -0,0 +1,45 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_internal.h
+ *
+ * Copyright (C) 2009-2011 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_STM32_STM32_INTERNAL_H
+#define __ARCH_ARM_SRC_STM32_STM32_INTERNAL_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include "stm32.h"
+
+#endif /* __ARCH_ARM_SRC_STM32_STM32_INTERNAL_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_irq.c b/nuttx/arch/arm/src/stm32/stm32_irq.c
new file mode 100644
index 000000000..36a5cf5fa
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_irq.c
@@ -0,0 +1,476 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_irq.c
+ * arch/arm/src/chip/stm32_irq.c
+ *
+ * Copyright (C) 2009-2012 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 <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/irq.h>
+
+#include "nvic.h"
+#include "up_arch.h"
+#include "os_internal.h"
+#include "up_internal.h"
+#include "stm32_internal.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* Enable NVIC debug features that are probably only desireable during
+ * bringup
+ */
+
+#undef STM32_IRQ_DEBUG
+
+/* Get a 32-bit version of the default priority */
+
+#define DEFPRIORITY32 \
+ (NVIC_SYSH_PRIORITY_DEFAULT << 24 |\
+ NVIC_SYSH_PRIORITY_DEFAULT << 16 |\
+ NVIC_SYSH_PRIORITY_DEFAULT << 8 |\
+ NVIC_SYSH_PRIORITY_DEFAULT)
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+volatile uint32_t *current_regs;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_dumpnvic
+ *
+ * Description:
+ * Dump some interesting NVIC registers
+ *
+ ****************************************************************************/
+
+#if defined(STM32_IRQ_DEBUG) && defined (CONFIG_DEBUG)
+static void stm32_dumpnvic(const char *msg, int irq)
+{
+ irqstate_t flags;
+
+ flags = irqsave();
+ slldbg("NVIC (%s, irq=%d):\n", msg, irq);
+ slldbg(" INTCTRL: %08x VECTAB: %08x\n",
+ getreg32(NVIC_INTCTRL), getreg32(NVIC_VECTAB));
+#if 0
+ slldbg(" SYSH ENABLE MEMFAULT: %08x BUSFAULT: %08x USGFAULT: %08x SYSTICK: %08x\n",
+ getreg32(NVIC_SYSHCON_MEMFAULTENA), getreg32(NVIC_SYSHCON_BUSFAULTENA),
+ getreg32(NVIC_SYSHCON_USGFAULTENA), getreg32(NVIC_SYSTICK_CTRL_ENABLE));
+#endif
+ slldbg(" IRQ ENABLE: %08x %08x %08x\n",
+ getreg32(NVIC_IRQ0_31_ENABLE), getreg32(NVIC_IRQ32_63_ENABLE),
+ getreg32(NVIC_IRQ64_95_ENABLE));
+ slldbg(" SYSH_PRIO: %08x %08x %08x\n",
+ getreg32(NVIC_SYSH4_7_PRIORITY), getreg32(NVIC_SYSH8_11_PRIORITY),
+ getreg32(NVIC_SYSH12_15_PRIORITY));
+ slldbg(" IRQ PRIO: %08x %08x %08x %08x\n",
+ getreg32(NVIC_IRQ0_3_PRIORITY), getreg32(NVIC_IRQ4_7_PRIORITY),
+ getreg32(NVIC_IRQ8_11_PRIORITY), getreg32(NVIC_IRQ12_15_PRIORITY));
+ slldbg(" %08x %08x %08x %08x\n",
+ getreg32(NVIC_IRQ16_19_PRIORITY), getreg32(NVIC_IRQ20_23_PRIORITY),
+ getreg32(NVIC_IRQ24_27_PRIORITY), getreg32(NVIC_IRQ28_31_PRIORITY));
+ slldbg(" %08x %08x %08x %08x\n",
+ getreg32(NVIC_IRQ32_35_PRIORITY), getreg32(NVIC_IRQ36_39_PRIORITY),
+ getreg32(NVIC_IRQ40_43_PRIORITY), getreg32(NVIC_IRQ44_47_PRIORITY));
+ slldbg(" %08x %08x %08x %08x\n",
+ getreg32(NVIC_IRQ48_51_PRIORITY), getreg32(NVIC_IRQ52_55_PRIORITY),
+ getreg32(NVIC_IRQ56_59_PRIORITY), getreg32(NVIC_IRQ60_63_PRIORITY));
+ slldbg(" %08x\n",
+ getreg32(NVIC_IRQ64_67_PRIORITY));
+ irqrestore(flags);
+}
+#else
+# define stm32_dumpnvic(msg, irq)
+#endif
+
+/****************************************************************************
+ * Name: stm32_nmi, stm32_busfault, stm32_usagefault, stm32_pendsv,
+ * stm32_dbgmonitor, stm32_pendsv, stm32_reserved
+ *
+ * Description:
+ * Handlers for various execptions. None are handled and all are fatal
+ * error conditions. The only advantage these provided over the default
+ * unexpected interrupt handler is that they provide a diagnostic output.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG
+static int stm32_nmi(int irq, FAR void *context)
+{
+ (void)irqsave();
+ dbg("PANIC!!! NMI received\n");
+ PANIC(OSERR_UNEXPECTEDISR);
+ return 0;
+}
+
+static int stm32_busfault(int irq, FAR void *context)
+{
+ (void)irqsave();
+ dbg("PANIC!!! Bus fault recived\n");
+ PANIC(OSERR_UNEXPECTEDISR);
+ return 0;
+}
+
+static int stm32_usagefault(int irq, FAR void *context)
+{
+ (void)irqsave();
+ dbg("PANIC!!! Usage fault received\n");
+ PANIC(OSERR_UNEXPECTEDISR);
+ return 0;
+}
+
+static int stm32_pendsv(int irq, FAR void *context)
+{
+ (void)irqsave();
+ dbg("PANIC!!! PendSV received\n");
+ PANIC(OSERR_UNEXPECTEDISR);
+ return 0;
+}
+
+static int stm32_dbgmonitor(int irq, FAR void *context)
+{
+ (void)irqsave();
+ dbg("PANIC!!! Debug Monitor receieved\n");
+ PANIC(OSERR_UNEXPECTEDISR);
+ return 0;
+}
+
+static int stm32_reserved(int irq, FAR void *context)
+{
+ (void)irqsave();
+ dbg("PANIC!!! Reserved interrupt\n");
+ PANIC(OSERR_UNEXPECTEDISR);
+ return 0;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_irqinfo
+ *
+ * Description:
+ * Given an IRQ number, provide the register and bit setting to enable or
+ * disable the irq.
+ *
+ ****************************************************************************/
+
+static int stm32_irqinfo(int irq, uint32_t *regaddr, uint32_t *bit)
+{
+ DEBUGASSERT(irq >= STM32_IRQ_NMI && irq < NR_IRQS);
+
+ /* Check for external interrupt */
+
+ if (irq >= STM32_IRQ_INTERRUPTS)
+ {
+ if (irq < STM32_IRQ_INTERRUPTS + 32)
+ {
+ *regaddr = NVIC_IRQ0_31_ENABLE;
+ *bit = 1 << (irq - STM32_IRQ_INTERRUPTS);
+ }
+ else if (irq < STM32_IRQ_INTERRUPTS + 64)
+ {
+ *regaddr = NVIC_IRQ32_63_ENABLE;
+ *bit = 1 << (irq - STM32_IRQ_INTERRUPTS - 32);
+ }
+ else if (irq < NR_IRQS)
+ {
+ *regaddr = NVIC_IRQ64_95_ENABLE;
+ *bit = 1 << (irq - STM32_IRQ_INTERRUPTS - 64);
+ }
+ else
+ {
+ return ERROR; /* Invalid interrupt */
+ }
+ }
+
+ /* Handle processor exceptions. Only a few can be disabled */
+
+ else
+ {
+ *regaddr = NVIC_SYSHCON;
+ if (irq == STM32_IRQ_MEMFAULT)
+ {
+ *bit = NVIC_SYSHCON_MEMFAULTENA;
+ }
+ else if (irq == STM32_IRQ_BUSFAULT)
+ {
+ *bit = NVIC_SYSHCON_BUSFAULTENA;
+ }
+ else if (irq == STM32_IRQ_USAGEFAULT)
+ {
+ *bit = NVIC_SYSHCON_USGFAULTENA;
+ }
+ else if (irq == STM32_IRQ_SYSTICK)
+ {
+ *regaddr = NVIC_SYSTICK_CTRL;
+ *bit = NVIC_SYSTICK_CTRL_ENABLE;
+ }
+ else
+ {
+ return ERROR; /* Invalid or unsupported exception */
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_irqinitialize
+ ****************************************************************************/
+
+void up_irqinitialize(void)
+{
+ uint32_t regaddr;
+ int num_priority_registers;
+
+ /* Disable all interrupts */
+
+ putreg32(0, NVIC_IRQ0_31_ENABLE);
+ putreg32(0, NVIC_IRQ32_63_ENABLE);
+
+ /* The standard location for the vector table is at the beginning of FLASH
+ * at address 0x0800:0000. If we are using the STMicro DFU bootloader, then
+ * the vector table will be offset to a different location in FLASH and we
+ * will need to set the NVIC vector location to this alternative location.
+ */
+
+#ifdef CONFIG_STM32_DFU
+ putreg32((uint32_t)stm32_vectors, NVIC_VECTAB);
+#endif
+
+ /* Set all interrupts (and exceptions) to the default priority */
+
+ putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY);
+ putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY);
+ putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY);
+
+ /* The NVIC ICTR register (bits 0-4) holds the number of of interrupt
+ * lines that the NVIC supports:
+ *
+ * 0 -> 32 interrupt lines, 8 priority registers
+ * 1 -> 64 " " " ", 16 priority registers
+ * 2 -> 96 " " " ", 32 priority registers
+ * ...
+ */
+
+ num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8;
+
+ /* Now set all of the interrupt lines to the default priority */
+
+ regaddr = NVIC_IRQ0_3_PRIORITY;
+ while (num_priority_registers--)
+ {
+ putreg32(DEFPRIORITY32, regaddr);
+ regaddr += 4;
+ }
+
+ /* currents_regs is non-NULL only while processing an interrupt */
+
+ current_regs = NULL;
+
+ /* Attach the SVCall and Hard Fault exception handlers. The SVCall
+ * exception is used for performing context switches; The Hard Fault
+ * must also be caught because a SVCall may show up as a Hard Fault
+ * under certain conditions.
+ */
+
+ irq_attach(STM32_IRQ_SVCALL, up_svcall);
+ irq_attach(STM32_IRQ_HARDFAULT, up_hardfault);
+
+ /* Set the priority of the SVCall interrupt */
+
+#ifdef CONFIG_ARCH_IRQPRIO
+/* up_prioritize_irq(STM32_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */
+#endif
+
+ /* If the MPU is enabled, then attach and enable the Memory Management
+ * Fault handler.
+ */
+
+#ifdef CONFIG_ARMV7M_MPU
+ irq_attach(STM32_IRQ_MEMFAULT, up_memfault);
+ up_enable_irq(STM32_IRQ_MEMFAULT);
+#endif
+
+ /* Attach all other processor exceptions (except reset and sys tick) */
+
+#ifdef CONFIG_DEBUG
+ irq_attach(STM32_IRQ_NMI, stm32_nmi);
+#ifndef CONFIG_ARMV7M_MPU
+ irq_attach(STM32_IRQ_MEMFAULT, up_memfault);
+#endif
+ irq_attach(STM32_IRQ_BUSFAULT, stm32_busfault);
+ irq_attach(STM32_IRQ_USAGEFAULT, stm32_usagefault);
+ irq_attach(STM32_IRQ_PENDSV, stm32_pendsv);
+ irq_attach(STM32_IRQ_DBGMONITOR, stm32_dbgmonitor);
+ irq_attach(STM32_IRQ_RESERVED, stm32_reserved);
+#endif
+
+ stm32_dumpnvic("initial", NR_IRQS);
+
+#ifndef CONFIG_SUPPRESS_INTERRUPTS
+
+ /* And finally, enable interrupts */
+
+ setbasepri(NVIC_SYSH_PRIORITY_MAX);
+ irqrestore(0);
+#endif
+}
+
+/****************************************************************************
+ * Name: up_disable_irq
+ *
+ * Description:
+ * Disable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_disable_irq(int irq)
+{
+ uint32_t regaddr;
+ uint32_t regval;
+ uint32_t bit;
+
+ if (stm32_irqinfo(irq, &regaddr, &bit) == 0)
+ {
+ /* Clear the appropriate bit in the register to enable the interrupt */
+
+ regval = getreg32(regaddr);
+ regval &= ~bit;
+ putreg32(regval, regaddr);
+ }
+ stm32_dumpnvic("disable", irq);
+}
+
+/****************************************************************************
+ * Name: up_enable_irq
+ *
+ * Description:
+ * Enable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_enable_irq(int irq)
+{
+ uint32_t regaddr;
+ uint32_t regval;
+ uint32_t bit;
+
+ if (stm32_irqinfo(irq, &regaddr, &bit) == 0)
+ {
+ /* Set the appropriate bit in the register to enable the interrupt */
+
+ regval = getreg32(regaddr);
+ regval |= bit;
+ putreg32(regval, regaddr);
+ }
+ stm32_dumpnvic("enable", irq);
+}
+
+/****************************************************************************
+ * Name: up_maskack_irq
+ *
+ * Description:
+ * Mask the IRQ and acknowledge it
+ *
+ ****************************************************************************/
+
+void up_maskack_irq(int irq)
+{
+ up_disable_irq(irq);
+}
+
+/****************************************************************************
+ * Name: up_prioritize_irq
+ *
+ * Description:
+ * Set the priority of an IRQ.
+ *
+ * Since this API is not supported on all architectures, it should be
+ * avoided in common implementations where possible.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_IRQPRIO
+int up_prioritize_irq(int irq, int priority)
+{
+ uint32_t regaddr;
+ uint32_t regval;
+ int shift;
+
+ DEBUGASSERT(irq >= STM32_IRQ_MEMFAULT && irq < NR_IRQS && (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN);
+
+ if (irq < STM32_IRQ_INTERRUPTS)
+ {
+ irq -= 4;
+ regaddr = NVIC_SYSH_PRIORITY(irq);
+ }
+ else
+ {
+ irq -= STM32_IRQ_INTERRUPTS;
+ regaddr = NVIC_IRQ_PRIORITY(irq);
+ }
+
+ regval = getreg32(regaddr);
+ shift = ((irq & 3) << 3);
+ regval &= ~(0xff << shift);
+ regval |= (priority << shift);
+ putreg32(regval, regaddr);
+
+ stm32_dumpnvic("prioritize", irq);
+ return OK;
+}
+#endif
diff --git a/nuttx/arch/arm/src/stm32/stm32_iwdg.c b/nuttx/arch/arm/src/stm32/stm32_iwdg.c
new file mode 100644
index 000000000..fd51ba0fe
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_iwdg.c
@@ -0,0 +1,711 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_iwdg.c
+ *
+ * Copyright (C) 2012 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 <nuttx/arch.h>
+
+#include <stdint.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/clock.h>
+#include <nuttx/watchdog.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "stm32_rcc.h"
+#include "chip/stm32_dbgmcu.h"
+#include "stm32_wdg.h"
+
+#if defined(CONFIG_WATCHDOG) && defined(CONFIG_STM32_IWDG)
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+/* Clocking *****************************************************************/
+/* The minimum frequency of the IWDG clock is:
+ *
+ * Fmin = Flsi / 256
+ *
+ * So the maximum delay (in milliseconds) is then:
+ *
+ * 1000 * IWDG_RLR_MAX / Fmin
+ *
+ * For example, if Flsi = 30Khz (the nominal, uncalibrathed value), then the
+ * maximum delay is:
+ *
+ * Fmin = 117.1875
+ * 1000 * 4095 / Fmin = 34,944 MSec
+ */
+
+#define IWDG_FMIN (STM32_LSI_FREQUENCY / 256)
+#define IWDG_MAXTIMEOUT (1000 * IWDG_RLR_MAX / IWDG_FMIN)
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_STM32_IWDG_DEFTIMOUT
+# define CONFIG_STM32_IWDG_DEFTIMOUT IWDG_MAXTIMEOUT
+#endif
+
+/* REVISIT: It appears that you can only setup the prescaler and reload
+ * registers once. After that, the SR register's PVU and RVU bits never go
+ * to zero. So we defer setting up these registers until the watchdog
+ * is started, then refuse any further attempts to change timeout.
+ */
+
+#define CONFIG_STM32_IWDG_ONETIMESETUP 1
+
+/* REVISIT: Another possibility is that we CAN change the prescaler and
+ * reload values after starting the timer. This option is untested but the
+ * implementation place conditioned on the following:
+ */
+
+#undef CONFIG_STM32_IWDG_DEFERREDSETUP
+
+/* But you can only try one at a time */
+
+#if defined(CONFIG_STM32_IWDG_ONETIMESETUP) && defined(CONFIG_STM32_IWDG_DEFERREDSETUP)
+# error "Both CONFIG_STM32_IWDG_ONETIMESETUP and CONFIG_STM32_IWDG_DEFERREDSETUP are defined"
+#endif
+
+/* Debug ********************************************************************/
+/* Non-standard debug that may be enabled just for testing the watchdog
+ * driver. NOTE: that only lldbg types are used so that the output is
+ * immediately available.
+ */
+
+#ifdef CONFIG_DEBUG_WATCHDOG
+# define wddbg lldbg
+# define wdvdbg llvdbg
+#else
+# define wddbg(x...)
+# define wdvdbg(x...)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+/* This structure provides the private representation of the "lower-half"
+ * driver state structure. This structure must be cast-compatible with the
+ * well-known watchdog_lowerhalf_s structure.
+ */
+
+struct stm32_lowerhalf_s
+{
+ FAR const struct watchdog_ops_s *ops; /* Lower half operations */
+ uint32_t lsifreq; /* The calibrated frequency of the LSI oscillator */
+ uint32_t timeout; /* The (actual) selected timeout */
+ uint32_t lastreset; /* The last reset time */
+ bool started; /* true: The watchdog timer has been started */
+ uint8_t prescaler; /* Clock prescaler value */
+ uint16_t reload; /* Timer reload value */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+/* Register operations ******************************************************/
+
+#if defined(CONFIG_STM32_IWDG_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint16_t stm32_getreg(uint32_t addr);
+static void stm32_putreg(uint16_t val, uint32_t addr);
+#else
+# define stm32_getreg(addr) getreg16(addr)
+# define stm32_putreg(val,addr) putreg16(val,addr)
+#endif
+
+static inline void stm32_setprescaler(FAR struct stm32_lowerhalf_s *priv);
+
+/* "Lower half" driver methods **********************************************/
+
+static int stm32_start(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status);
+static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+/* "Lower half" driver methods */
+
+static const struct watchdog_ops_s g_wdgops =
+{
+ .start = stm32_start,
+ .stop = stm32_stop,
+ .keepalive = stm32_keepalive,
+ .getstatus = stm32_getstatus,
+ .settimeout = stm32_settimeout,
+ .capture = NULL,
+ .ioctl = NULL,
+};
+
+/* "Lower half" driver state */
+
+static struct stm32_lowerhalf_s g_wdgdev;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_getreg
+ *
+ * Description:
+ * Get the contents of an STM32 IWDG register
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_IWDG_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint16_t stm32_getreg(uint32_t addr)
+{
+ static uint32_t prevaddr = 0;
+ static uint32_t count = 0;
+ static uint16_t preval = 0;
+
+ /* Read the value from the register */
+
+ uint16_t val = getreg16(addr);
+
+ /* Is this the same value that we read from the same registe last time? Are
+ * we polling the register? If so, suppress some of the output.
+ */
+
+ if (addr == prevaddr && val == preval)
+ {
+ if (count == 0xffffffff || ++count > 3)
+ {
+ if (count == 4)
+ {
+ lldbg("...\n");
+ }
+ return val;
+ }
+ }
+
+ /* No this is a new address or value */
+
+ else
+ {
+ /* Did we print "..." for the previous value? */
+
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
+
+ lldbg("[repeats %d more times]\n", count-3);
+ }
+
+ /* Save the new address, value, and count */
+
+ prevaddr = addr;
+ preval = val;
+ count = 1;
+ }
+
+ /* Show the register value read */
+
+ lldbg("%08x->%04x\n", addr, val);
+ return val;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_putreg
+ *
+ * Description:
+ * Set the contents of an STM32 register to a value
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_IWDG_REGDEBUG) && defined(CONFIG_DEBUG)
+static void stm32_putreg(uint16_t val, uint32_t addr)
+{
+ /* Show the register value being written */
+
+ lldbg("%08x<-%04x\n", addr, val);
+
+ /* Write the value */
+
+ putreg16(val, addr);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_setprescaler
+ *
+ * Description:
+ * Set up the prescaler and reload values. This seems to be something
+ * that can only be done one time.
+ *
+ * Input Parameters:
+ * priv - A pointer the internal representation of the "lower-half"
+ * driver state structure.
+ * timeout - The new timeout value in millisecnds.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static inline void stm32_setprescaler(FAR struct stm32_lowerhalf_s *priv)
+{
+ /* Enable write access to IWDG_PR and IWDG_RLR registers */
+
+ stm32_putreg(IWDG_KR_KEY_ENABLE, STM32_IWDG_KR);
+
+ /* Wait for the PVU and RVU bits to be reset be hardware. These bits
+ * were set the last time that the PR register was written and may not
+ * yet be cleared.
+ *
+ * If the setup is only permitted one time, then this wait should not
+ * be necessary.
+ */
+
+#ifndef CONFIG_STM32_IWDG_ONETIMESETUP
+ while ((stm32_getreg(STM32_IWDG_SR) & (IWDG_SR_PVU|IWDG_SR_RVU)) != 0);
+#endif
+
+ /* Set the prescaler */
+
+ stm32_putreg((uint16_t)priv->prescaler << IWDG_PR_SHIFT, STM32_IWDG_PR);
+
+ /* Set the reload value */
+
+ stm32_putreg((uint16_t)priv->reload, STM32_IWDG_RLR);
+
+ /* Reload the counter (and disable write access) */
+
+ stm32_putreg(IWDG_KR_KEY_RELOAD, STM32_IWDG_KR);
+}
+
+/****************************************************************************
+ * Name: stm32_start
+ *
+ * Description:
+ * Start the watchdog timer, resetting the time to the current timeout,
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_start(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ irqstate_t flags;
+
+ wdvdbg("Entry: started=%d\n");
+ DEBUGASSERT(priv);
+
+ /* Have we already been started? */
+
+ if (!priv->started)
+ {
+ /* REVISIT: It appears that you can only setup the prescaler and reload
+ * registers once. After that, the SR register's PVU and RVU bits never go
+ * to zero. So we defer setting up these registers until the watchdog
+ * is started, then refuse any further attempts to change timeout.
+ */
+
+ /* Set up prescaler and reload value for the selected timeout before
+ * starting the watchdog timer.
+ */
+
+#if defined(CONFIG_STM32_IWDG_ONETIMESETUP) || defined(CONFIG_STM32_IWDG_DEFERREDSETUP)
+ stm32_setprescaler(priv);
+#endif
+
+ /* Enable IWDG (the LSI oscillator will be enabled by hardware). NOTE:
+ * If the "Hardware watchdog" feature is enabled through the device option
+ * bits, the watchdog is automatically enabled at power-on.
+ */
+
+ flags = irqsave();
+ stm32_putreg(IWDG_KR_KEY_START, STM32_IWDG_KR);
+ priv->lastreset = clock_systimer();
+ priv->started = true;
+ irqrestore(flags);
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_stop
+ *
+ * Description:
+ * Stop the watchdog timer
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower)
+{
+ /* There is no way to disable the IDWG timer once it has been started */
+
+ wdvdbg("Entry\n");
+ return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: stm32_keepalive
+ *
+ * Description:
+ * Reset the watchdog timer to the current timeout value, prevent any
+ * imminent watchdog timeouts. This is sometimes referred as "pinging"
+ * the atchdog timer or "petting the dog".
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ irqstate_t flags;
+
+ wdvdbg("Entry\n");
+
+ /* Reload the IWDG timer */
+
+ flags = irqsave();
+ stm32_putreg(IWDG_KR_KEY_RELOAD, STM32_IWDG_KR);
+ priv->lastreset = clock_systimer();
+ irqrestore(flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_getstatus
+ *
+ * Description:
+ * Get the current watchdog timer status
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ * stawtus - The location to return the watchdog status information.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ uint32_t ticks;
+ uint32_t elapsed;
+
+ wdvdbg("Entry\n");
+ DEBUGASSERT(priv);
+
+ /* Return the status bit */
+
+ status->flags = WDFLAGS_RESET;
+ if (priv->started)
+ {
+ status->flags |= WDFLAGS_ACTIVE;
+ }
+
+ /* Return the actual timeout in milliseconds */
+
+ status->timeout = priv->timeout;
+
+ /* Get the elapsed time since the last ping */
+
+ ticks = clock_systimer() - priv->lastreset;
+ elapsed = (int32_t)TICK2MSEC(ticks);
+
+ if (elapsed > priv->timeout)
+ {
+ elapsed = priv->timeout;
+ }
+
+ /* Return the approximate time until the watchdog timer expiration */
+
+ status->timeleft = priv->timeout - elapsed;
+
+ wdvdbg("Status :\n");
+ wdvdbg(" flags : %08x\n", status->flags);
+ wdvdbg(" timeout : %d\n", status->timeout);
+ wdvdbg(" timeleft : %d\n", status->timeleft);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_settimeout
+ *
+ * Description:
+ * Set a new timeout value (and reset the watchdog timer)
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ * timeout - The new timeout value in millisecnds.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ uint32_t fiwdg;
+ uint64_t reload;
+ int prescaler;
+ int shift;
+
+ wdvdbg("Entry: timeout=%d\n", timeout);
+ DEBUGASSERT(priv);
+
+ /* Can this timeout be represented? */
+
+ if (timeout < 1 || timeout > IWDG_MAXTIMEOUT)
+ {
+ wddbg("Cannot represent timeout=%d > %d\n",
+ timeout, IWDG_MAXTIMEOUT);
+ return -ERANGE;
+ }
+
+ /* REVISIT: It appears that you can only setup the prescaler and reload
+ * registers once. After that, the SR register's PVU and RVU bits never go
+ * to zero.
+ */
+
+#ifdef CONFIG_STM32_IWDG_ONETIMESETUP
+ if (priv->started)
+ {
+ wddbg("Timer is already started\n");
+ return -EBUSY;
+ }
+#endif
+
+ /* Select the smallest prescaler that will result in a reload value that is
+ * less than the maximum.
+ */
+
+ for (prescaler = 0; ; prescaler++)
+ {
+ /* PR = 0 -> Divider = 4 = 1 << 2
+ * PR = 1 -> Divider = 8 = 1 << 3
+ * PR = 2 -> Divider = 16 = 1 << 4
+ * PR = 3 -> Divider = 32 = 1 << 5
+ * PR = 4 -> Divider = 64 = 1 << 6
+ * PR = 5 -> Divider = 128 = 1 << 7
+ * PR = 6 -> Divider = 256 = 1 << 8
+ * PR = n -> Divider = 1 << (n+2)
+ */
+
+ shift = prescaler + 2;
+
+ /* Get the IWDG counter frequency in Hz. For a nominal 32Khz LSI clock,
+ * this is value in the range of 7500 and 125.
+ */
+
+ fiwdg = priv->lsifreq >> shift;
+
+ /* We want:
+ * 1000 * reload / Fiwdg = timeout
+ * Or:
+ * reload = Fiwdg * timeout / 1000
+ */
+
+ reload = (uint64_t)fiwdg * (uint64_t)timeout / 1000;
+
+ /* If this reload valid is less than the maximum or we are not ready
+ * at the prescaler value, then break out of the loop to use these
+ * settings.
+ */
+
+ if (reload <= IWDG_RLR_MAX || prescaler == 6)
+ {
+ /* Note that we explicity break out of the loop rather than using
+ * the 'for' loop termination logic because we do not want the
+ * value of prescaler to be incremented.
+ */
+
+ break;
+ }
+ }
+
+ /* Make sure that the final reload value is within range */
+
+ if (reload > IWDG_RLR_MAX)
+ {
+ reload = IWDG_RLR_MAX;
+ }
+
+ /* Get the actual timeout value in milliseconds.
+ *
+ * We have:
+ * reload = Fiwdg * timeout / 1000
+ * So we want:
+ * timeout = 1000 * reload / Fiwdg
+ */
+
+ priv->timeout = (1000 * (uint32_t)reload) / fiwdg;
+
+ /* Save setup values for later use */
+
+ priv->prescaler = prescaler;
+ priv->reload = reload;
+
+ /* Write the prescaler and reload values to the IWDG registers.
+ *
+ * REVISIT: It appears that you can only setup the prescaler and reload
+ * registers once. After that, the SR register's PVU and RVU bits never go
+ * to zero.
+ */
+
+#ifndef CONFIG_STM32_IWDG_ONETIMESETUP
+ /* If CONFIG_STM32_IWDG_DEFERREDSETUP is selected, then perform the register
+ * configuration only if the timer has been started.
+ */
+
+#ifdef CONFIG_STM32_IWDG_DEFERREDSETUP
+ if (priv->started)
+#endif
+ {
+ stm32_setprescaler(priv);
+ }
+#endif
+
+ wdvdbg("prescaler=%d fiwdg=%d reload=%d\n", prescaler, fiwdg, reload);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_iwdginitialize
+ *
+ * Description:
+ * Initialize the IWDG watchdog time. The watchdog timer is intialized and
+ * registers as 'devpath. The initial state of the watchdog time is
+ * disabled.
+ *
+ * Input Parameters:
+ * devpath - The full path to the watchdog. This should be of the form
+ * /dev/watchdog0
+ * lsifreq - The calibrated LSI clock frequency
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+void stm32_iwdginitialize(FAR const char *devpath, uint32_t lsifreq)
+{
+ FAR struct stm32_lowerhalf_s *priv = &g_wdgdev;
+
+ wdvdbg("Entry: devpath=%s lsifreq=%d\n", devpath, lsifreq);
+
+ /* NOTE we assume that clocking to the IWDG has already been provided by
+ * the RCC initialization logic.
+ */
+
+ /* Initialize the driver state structure. */
+
+ priv->ops = &g_wdgops;
+ priv->lsifreq = lsifreq;
+ priv->started = false;
+
+ /* Make sure that the LSI ocsillator is enabled. NOTE: The LSI oscillator
+ * is enabled here but is not disabled by this file (because this file does
+ * not know the the global usage of the oscillator. Any clock management
+ * logic (say, as part of a power management scheme) needs handle other
+ * LSI controls outside of this file.
+ */
+
+ stm32_rcc_enablelsi();
+ wdvdbg("RCC CSR: %08x\n", getreg32(STM32_RCC_CSR));
+
+ /* Select an arbitrary initial timeout value. But don't start the watchdog
+ * yet. NOTE: If the "Hardware watchdog" feature is enabled through the
+ * device option bits, the watchdog is automatically enabled at power-on.
+ */
+
+ stm32_settimeout((FAR struct watchdog_lowerhalf_s *)priv, CONFIG_STM32_IWDG_DEFTIMOUT);
+
+ /* Register the watchdog driver as /dev/watchdog0 */
+
+ (void)watchdog_register(devpath, (FAR struct watchdog_lowerhalf_s *)priv);
+
+ /* When the microcontroller enters debug mode (Cortex™-M4F core halted),
+ * the IWDG counter either continues to work normally or stops, depending
+ * on DBG_WIDG_STOP configuration bit in DBG module.
+ */
+
+#if defined(CONFIG_STM32_JTAG_FULL_ENABLE) || \
+ defined(CONFIG_STM32_JTAG_NOJNTRST_ENABLE) || \
+ defined(CONFIG_STM32_JTAG_SW_ENABLE)
+ {
+ uint32_t cr = getreg32(STM32_DBGMCU_CR);
+ cr |= DBGMCU_CR_IWDGSTOP;
+ putreg32(cr, STM32_DBGMCU_CR);
+ }
+#endif
+}
+
+#endif /* CONFIG_WATCHDOG && CONFIG_STM32_IWDG */
diff --git a/nuttx/arch/arm/src/stm32/stm32_lowputc.c b/nuttx/arch/arm/src/stm32/stm32_lowputc.c
new file mode 100644
index 000000000..14f4efae4
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_lowputc.c
@@ -0,0 +1,428 @@
+/**************************************************************************
+ * arch/arm/src/stm32/stm32_lowputc.c
+ *
+ * Copyright (C) 2009, 2012 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_rcc.h"
+#include "stm32_gpio.h"
+#include "stm32_uart.h"
+#include "stm32_internal.h"
+
+/**************************************************************************
+ * Private Definitions
+ **************************************************************************/
+/* Select USART parameters for the selected console */
+
+#if defined(CONFIG_USART1_SERIAL_CONSOLE)
+# define STM32_CONSOLE_BASE STM32_USART1_BASE
+# define STM32_APBCLOCK STM32_PCLK2_FREQUENCY
+# define STM32_CONSOLE_BAUD CONFIG_USART1_BAUD
+# define STM32_CONSOLE_BITS CONFIG_USART1_BITS
+# define STM32_CONSOLE_PARITY CONFIG_USART1_PARITY
+# define STM32_CONSOLE_2STOP CONFIG_USART1_2STOP
+# define STM32_CONSOLE_TX GPIO_USART1_TX
+# define STM32_CONSOLE_RX GPIO_USART1_RX
+#elif defined(CONFIG_USART2_SERIAL_CONSOLE)
+# define STM32_CONSOLE_BASE STM32_USART2_BASE
+# define STM32_APBCLOCK STM32_PCLK1_FREQUENCY
+# define STM32_CONSOLE_BAUD CONFIG_USART2_BAUD
+# define STM32_CONSOLE_BITS CONFIG_USART2_BITS
+# define STM32_CONSOLE_PARITY CONFIG_USART2_PARITY
+# define STM32_CONSOLE_2STOP CONFIG_USART2_2STOP
+# define STM32_CONSOLE_TX GPIO_USART2_TX
+# define STM32_CONSOLE_RX GPIO_USART2_RX
+#elif defined(CONFIG_USART3_SERIAL_CONSOLE)
+# define STM32_CONSOLE_BASE STM32_USART3_BASE
+# define STM32_APBCLOCK STM32_PCLK1_FREQUENCY
+# define STM32_CONSOLE_BAUD CONFIG_USART3_BAUD
+# define STM32_CONSOLE_BITS CONFIG_USART3_BITS
+# define STM32_CONSOLE_PARITY CONFIG_USART3_PARITY
+# define STM32_CONSOLE_2STOP CONFIG_USART3_2STOP
+# define STM32_CONSOLE_TX GPIO_USART3_TX
+# define STM32_CONSOLE_RX GPIO_USART3_RX
+#elif defined(CONFIG_USART4_SERIAL_CONSOLE)
+# define STM32_CONSOLE_BASE STM32_UART4_BASE
+# define STM32_APBCLOCK STM32_PCLK1_FREQUENCY
+# define STM32_CONSOLE_BAUD CONFIG_USART4_BAUD
+# define STM32_CONSOLE_BITS CONFIG_USART4_BITS
+# define STM32_CONSOLE_PARITY CONFIG_USART4_PARITY
+# define STM32_CONSOLE_2STOP CONFIG_USART4_2STOP
+# define STM32_CONSOLE_TX GPIO_UART4_TX
+# define STM32_CONSOLE_RX GPIO_UART4_RX
+#elif defined(CONFIG_USART5_SERIAL_CONSOLE)
+# define STM32_CONSOLE_BASE STM32_UART5_BASE
+# define STM32_APBCLOCK STM32_PCLK1_FREQUENCY
+# define STM32_CONSOLE_BAUD CONFIG_USART5_BAUD
+# define STM32_CONSOLE_BITS CONFIG_USART5_BITS
+# define STM32_CONSOLE_PARITY CONFIG_USART5_PARITY
+# define STM32_CONSOLE_2STOP CONFIG_USART5_2STOP
+# define STM32_CONSOLE_TX GPIO_UART5_TX
+# define STM32_CONSOLE_RX GPIO_UART5_RX
+#elif defined(CONFIG_USART6_SERIAL_CONSOLE)
+# define STM32_CONSOLE_BASE STM32_USART6_BASE
+# define STM32_APBCLOCK STM32_PCLK2_FREQUENCY
+# define STM32_CONSOLE_BAUD CONFIG_USART6_BAUD
+# define STM32_CONSOLE_BITS CONFIG_USART6_BITS
+# define STM32_CONSOLE_PARITY CONFIG_USART6_PARITY
+# define STM32_CONSOLE_2STOP CONFIG_USART6_2STOP
+# define STM32_CONSOLE_TX GPIO_USART6_TX
+# define STM32_CONSOLE_RX GPIO_USART6_RX
+#endif
+
+/* CR1 settings */
+
+#if STM32_CONSOLE_BITS == 9
+# define USART_CR1_M_VALUE USART_CR1_M
+#else
+# define USART_CR1_M_VALUE 0
+#endif
+
+#if STM32_CONSOLE_PARITY == 1
+# define USART_CR1_PARITY_VALUE (USART_CR1_PCE|USART_CR1_PS)
+#elif STM32_CONSOLE_PARITY == 2
+# define USART_CR1_PARITY_VALUE USART_CR1_PCE
+#else
+# define USART_CR1_PARITY_VALUE 0
+#endif
+
+#define USART_CR1_CLRBITS (USART_CR1_M|USART_CR1_PCE|USART_CR1_PS|USART_CR1_TE|USART_CR1_RE|USART_CR1_ALLINTS)
+#define USART_CR1_SETBITS (USART_CR1_M_VALUE|USART_CR1_PARITY_VALUE)
+
+/* CR2 settings */
+
+#if STM32_CONSOLE_2STOP != 0
+# define USART_CR2_STOP2_VALUE USART_CR2_STOP2
+#else
+# define USART_CR2_STOP2_VALUE 0
+#endif
+
+#define USART_CR2_CLRBITS (USART_CR2_STOP_MASK|USART_CR2_CLKEN|USART_CR2_CPOL|USART_CR2_CPHA|USART_CR2_LBCL|USART_CR2_LBDIE)
+#define USART_CR2_SETBITS USART_CR2_STOP2_VALUE
+
+/* CR3 settings */
+
+#define USART_CR3_CLRBITS (USART_CR3_CTSIE|USART_CR3_CTSE|USART_CR3_RTSE|USART_CR3_EIE)
+#define USART_CR3_SETBITS 0
+
+/* Calculate USART BAUD rate divider
+ *
+ * The baud rate for the receiver and transmitter (Rx and Tx) are both set to
+ * the same value as programmed in the Mantissa and Fraction values of USARTDIV.
+ *
+ * baud = fCK / (16 * usartdiv)
+ * usartdiv = fCK / (16 * baud)
+ *
+ * Where fCK is the input clock to the peripheral (PCLK1 for USART2, 3, 4, 5
+ * or PCLK2 for USART1). Example, fCK=72MHz baud=115200, usartdiv=39.0625=39 1/16th;
+ *
+ * First calculate:
+ *
+ * usartdiv32 = 32 * usartdiv = fCK / (baud/2)
+ *
+ * (NOTE: all standard baud values are even so dividing by two does not
+ * lose precision). Eg. (same fCK and buad), usartdiv32 = 1250
+ */
+
+#define STM32_USARTDIV32 (STM32_APBCLOCK / (STM32_CONSOLE_BAUD >> 1))
+
+/* The mantissa is then usartdiv32 / 32:
+ *
+ * mantissa = usartdiv32 / 32/
+ *
+ * Eg. usartdiv32=1250, mantissa = 39
+ */
+
+#define STM32_MANTISSA (STM32_USARTDIV32 >> 5)
+
+/* And the fraction:
+ *
+ * fraction = (usartdiv32 - mantissa*32 + 1) / 2
+ *
+ * Eg., (1,250 - 39*32 + 1)/2 = 1 (or 0.0625)
+ */
+
+#define STM32_FRACTION ((STM32_USARTDIV32 - (STM32_MANTISSA << 5) + 1) >> 1)
+
+/* And, finally, the BRR value is: */
+
+#define STM32_BRR_VALUE ((STM32_MANTISSA << USART_BRR_MANT_SHIFT) | (STM32_FRACTION << USART_BRR_FRAC_SHIFT))
+
+/**************************************************************************
+ * Private Types
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Function Prototypes
+ **************************************************************************/
+
+/**************************************************************************
+ * Global Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Public Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Name: up_lowputc
+ *
+ * Description:
+ * Output one byte on the serial console
+ *
+ **************************************************************************/
+
+void up_lowputc(char ch)
+{
+#ifdef HAVE_CONSOLE
+ /* Wait until the TX data register is empty */
+
+ while ((getreg32(STM32_CONSOLE_BASE + STM32_USART_SR_OFFSET) & USART_SR_TXE) == 0);
+
+ /* Then send the character */
+
+ putreg32((uint32_t)ch, STM32_CONSOLE_BASE + STM32_USART_DR_OFFSET);
+#endif
+}
+
+/**************************************************************************
+ * Name: stm32_lowsetup
+ *
+ * Description:
+ * This performs basic initialization of the USART used for the serial
+ * console. Its purpose is to get the console output availabe as soon
+ * as possible.
+ *
+ **************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F10XX)
+void stm32_lowsetup(void)
+{
+#if defined(HAVE_UART)
+ uint32_t mapr;
+#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG)
+ uint32_t cr;
+#endif
+
+ /* Set up the pin mapping registers for the selected U[S]ARTs.
+ *
+ * NOTE: Clocking for selected U[S]ARTs was already provided in stm32_rcc.c
+ */
+
+ mapr = getreg32(STM32_AFIO_MAPR);
+
+#ifdef CONFIG_STM32_USART1
+ /* Assume default pin mapping:
+ *
+ * Alternate USART1_REMAP USART1_REMAP
+ * Function = 0 = 1
+ * ---------- ------------ ------------
+ * USART1_TX PA9 PB6
+ * USART1_RX PA10 PB7
+ */
+
+#ifdef CONFIG_STM32_USART1_REMAP
+ mapr |= AFIO_MAPR_USART1_REMAP;
+#else
+ mapr &= ~AFIO_MAPR_USART1_REMAP;
+#endif
+#endif /* CONFIG_STM32_USART1 */
+
+#ifdef CONFIG_STM32_USART2
+ /* Assume default pin mapping:
+ *
+ * Alternate USART2_REMAP USART2_REMAP
+ * Function = 0 = 1
+ * ---------- ------------ ------------
+ * USART2_CTS PA0 PD3
+ * USART2_RTS PA1 PD4
+ * USART2_TX PA2 PD5
+ * USART2_RX PA3 PD6
+ * USART3_CK PA4 PD7
+ */
+
+#ifdef CONFIG_STM32_USART2_REMAP
+ mapr |= AFIO_MAPR_USART2_REMAP;
+#else
+ mapr &= ~AFIO_MAPR_USART2_REMAP;
+#endif
+#endif /* CONFIG_STM32_USART2 */
+
+ /* Assume default pin mapping:
+ *
+ * Alternate USART3_REMAP[1:0] USART3_REMAP[1:0] USART3_REMAP[1:0]
+ * Function = “00†(no remap) = “01†(partial remap) = “11†(full remap)
+ * ---------_ ------------------ ---------------------- --------------------
+ * USART3_TX PB10 PC10 PD8
+ * USART3_RX PB11 PC11 PD9
+ * USART3_CK PB12 PC12 PD10
+ * USART3_CTS PB13 PB13 PD11
+ * USART3_RTS PB14 PB14 PD12
+ */
+
+ mapr &= ~AFIO_MAPR_USART3_REMAP_MASK;
+
+#ifdef CONFIG_STM32_USART3
+#if defined(CONFIG_STM32_USART3_PARTIAL_REMAP)
+ mapr |= AFIO_MAPR_USART3_PARTREMAP;
+#elif defined(CONFIG_STM32_USART3_FULL_REMAP)
+ mapr |= AFIO_MAPR_USART3_FULLREMAP;
+#endif
+#endif /* CONFIG_STM32_USART3 */
+
+ putreg32(mapr, STM32_AFIO_MAPR);
+
+ /* Configure GPIO pins needed for rx/tx. */
+
+#ifdef STM32_CONSOLE_TX
+ stm32_configgpio(STM32_CONSOLE_TX);
+ stm32_configgpio(STM32_CONSOLE_TX);
+#endif
+
+ /* Enable and configure the selected console device */
+
+#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG)
+ /* Configure CR2 */
+
+ cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR2_OFFSET);
+ cr &= ~USART_CR2_CLRBITS;
+ cr |= USART_CR2_SETBITS;
+ putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR2_OFFSET);
+
+ /* Configure CR1 */
+
+ cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET);
+ cr &= ~USART_CR1_CLRBITS;
+ cr |= USART_CR1_SETBITS;
+ putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET);
+
+ /* Configure CR3 */
+
+ cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR3_OFFSET);
+ cr &= ~USART_CR3_CLRBITS;
+ cr |= USART_CR3_SETBITS;
+ putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR3_OFFSET);
+
+ /* Configure the USART Baud Rate */
+
+ putreg32(STM32_BRR_VALUE, STM32_CONSOLE_BASE + STM32_USART_BRR_OFFSET);
+
+ /* Enable Rx, Tx, and the USART */
+
+ cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET);
+ cr |= (USART_CR1_UE|USART_CR1_TE|USART_CR1_RE);
+ putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET);
+#endif
+#endif /* HAVE_UART */
+}
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+void stm32_lowsetup(void)
+{
+#if defined(HAVE_UART)
+#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG)
+ uint32_t cr;
+#endif
+
+ /* Enable the console USART and configure GPIO pins needed for rx/tx.
+ *
+ * NOTE: Clocking for selected U[S]ARTs was already provided in stm32_rcc.c
+ */
+
+#ifdef STM32_CONSOLE_TX
+ stm32_configgpio(STM32_CONSOLE_TX);
+ stm32_configgpio(STM32_CONSOLE_TX);
+#endif
+
+ /* Enable and configure the selected console device */
+
+#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG)
+ /* Configure CR2 */
+
+ cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR2_OFFSET);
+ cr &= ~USART_CR2_CLRBITS;
+ cr |= USART_CR2_SETBITS;
+ putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR2_OFFSET);
+
+ /* Configure CR1 */
+
+ cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET);
+ cr &= ~USART_CR1_CLRBITS;
+ cr |= USART_CR1_SETBITS;
+ putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET);
+
+ /* Configure CR3 */
+
+ cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR3_OFFSET);
+ cr &= ~USART_CR3_CLRBITS;
+ cr |= USART_CR3_SETBITS;
+ putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR3_OFFSET);
+
+ /* Configure the USART Baud Rate */
+
+ putreg32(STM32_BRR_VALUE, STM32_CONSOLE_BASE + STM32_USART_BRR_OFFSET);
+
+ /* Enable Rx, Tx, and the USART */
+
+ cr = getreg32(STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET);
+ cr |= (USART_CR1_UE|USART_CR1_TE|USART_CR1_RE);
+ putreg32(cr, STM32_CONSOLE_BASE + STM32_USART_CR1_OFFSET);
+#endif
+#endif /* HAVE_UART */
+}
+#else
+# error "Unsupported STM32 chip"
+#endif
+
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_lowputc.h b/nuttx/arch/arm/src/stm32/stm32_lowputc.h
new file mode 100644
index 000000000..edcc78d8f
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_lowputc.h
@@ -0,0 +1,79 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_lowputc.h
+ *
+ * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_STM32_LOWPUTC_H
+#define __ARCH_ARM_SRC_STM32_STM32_LOWPUTC_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Name: stm32_lowsetup
+ *
+ * Description:
+ * Called at the very beginning of _start. Performs low level initialization
+ * of serial console.
+ *
+ ************************************************************************************/
+
+EXTERN void stm32_lowsetup(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_LOWPUTC_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_lse.c b/nuttx/arch/arm/src/stm32/stm32_lse.c
new file mode 100644
index 000000000..931199efd
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_lse.c
@@ -0,0 +1,105 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_lse.c
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.orgr>
+ *
+ * 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 "up_arch.h"
+
+#include "stm32_rcc.h"
+#include "stm32_waste.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_rcc_enablelse
+ *
+ * Description:
+ * Enable the External Low-Speed (LSE) Oscillator and, if the RTC is
+ * configured, setup the LSE as the RTC clock source, and enable the RTC.
+ *
+ * Todo:
+ * Check for LSE good timeout and return with -1,
+ *
+ ****************************************************************************/
+
+void stm32_rcc_enablelse(void)
+{
+ /* Enable the External Low-Speed (LSE) Oscillator by setting the LSEON bit
+ * the RCC BDCR register.
+ */
+
+ modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_LSEON);
+
+ /* Wait for the LSE clock to be ready */
+
+ while ((getreg16(STM32_RCC_BDCR) & RCC_BDCR_LSERDY) == 0)
+ {
+ up_waste();
+ }
+
+ /* The primariy purpose of the LSE clock is to drive the RTC. The RTC could
+ * also be driven by the LSI (but that would be very inaccurate) or by the
+ * HSE (but that would prohibit low-power operation)
+ *
+ * Select LSE as RTC Clock Source by setting the RTCSEL field of the RCC BDCR
+ * register.
+ */
+
+#ifdef CONFIG_RTC
+ modifyreg16(STM32_RCC_BDCR, RCC_BDCR_RTCSEL_MASK, RCC_BDCR_RTCSEL_LSE);
+
+ /* Enable the RTC Clock by setting the RTCEN bit in the RCC BDCR register */
+
+ modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_RTCEN);
+#endif
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_lsi.c b/nuttx/arch/arm/src/stm32/stm32_lsi.c
new file mode 100644
index 000000000..e365fbf06
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_lsi.c
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_lsi.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.orgr>
+ *
+ * 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 "up_arch.h"
+
+#include "stm32_rcc.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_rcc_enablelsi
+ *
+ * Description:
+ * Enable the Internal Low-Speed (LSI) RC Oscillator.
+ *
+ ****************************************************************************/
+
+void stm32_rcc_enablelsi(void)
+{
+ /* Enable the Internal Low-Speed (LSI) RC Oscillator by setting the LSION bit
+ * the RCC CSR register.
+ */
+
+ modifyreg32(STM32_RCC_CSR, 0, RCC_CSR_LSION);
+
+ /* Wait for the internal RC 40 kHz oscillator to be stable. */
+
+ while ((getreg32(STM32_RCC_CSR) & RCC_CSR_LSIRDY) == 0);
+}
+
+/****************************************************************************
+ * Name: stm32_rcc_disablelsi
+ *
+ * Description:
+ * Disable the Internal Low-Speed (LSI) RC Oscillator.
+ *
+ ****************************************************************************/
+
+void stm32_rcc_disablelsi(void)
+{
+ /* Enable the Internal Low-Speed (LSI) RC Oscillator by setting the LSION bit
+ * the RCC CSR register.
+ */
+
+ modifyreg32(STM32_RCC_CSR, RCC_CSR_LSION, 0);
+
+ /* LSIRDY should go low after 3 LSI clock cycles */
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfs.h b/nuttx/arch/arm/src/stm32/stm32_otgfs.h
new file mode 100644
index 000000000..74f2bdd31
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfs.h
@@ -0,0 +1,93 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_otgfs.h
+ *
+ * Copyright (C) 2012 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_STM32_STM32_OTGFS_H
+#define __ARCH_ARM_SRC_STM32_STM32_OTGFS_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#include "stm32.h"
+#include "chip/stm32_otgfs.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+
+#ifndef CONFIG_OTGFS_PRI
+# define CONFIG_OTGFS_PRI NVIC_SYSH_PRIORITY_DEFAULT
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Name: stm32_usbsuspend
+ *
+ * Description:
+ * Board logic must provide the stm32_usbsuspend logic if the OTG FS device driver
+ * is used. This function is called whenever the USB enters or leaves suspend
+ * mode. This is an opportunity for the board logic to shutdown clocks, power,
+ * etc. while the USB is suspended.
+ *
+ ************************************************************************************/
+
+EXTERN void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_OTGFS_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
new file mode 100644
index 000000000..39c40d80a
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
@@ -0,0 +1,5413 @@
+/*******************************************************************************
+ * arch/arm/src/stm32/stm32_usbdev.c
+ *
+ * Copyright (C) 2012 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/usb/usb.h>
+#include <nuttx/usb/usbdev.h>
+#include <nuttx/usb/usbdev_trace.h>
+
+#include <arch/irq.h>
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "up_arch.h"
+#include "up_internal.h"
+
+#include "stm32_otgfs.h"
+
+#if defined(CONFIG_USBDEV) && defined(CONFIG_STM32_OTGFS)
+
+/*******************************************************************************
+ * Definitions
+ *******************************************************************************/
+/* Configuration ***************************************************************/
+
+#ifndef CONFIG_USBDEV_EP0_MAXSIZE
+# define CONFIG_USBDEV_EP0_MAXSIZE 64
+#endif
+
+#ifndef CONFIG_USBDEV_SETUP_MAXDATASIZE
+# define CONFIG_USBDEV_SETUP_MAXDATASIZE CONFIG_USBDEV_EP0_MAXSIZE
+#endif
+
+#ifndef CONFIG_USBDEV_MAXPOWER
+# define CONFIG_USBDEV_MAXPOWER 100 /* mA */
+#endif
+
+/* There is 1.25Kb of FIFO memory. The default partitions this memory
+ * so that there is a TxFIFO allocated for each endpoint and with more
+ * memory provided for the common RxFIFO. A more knowledge-able
+ * configuration would not allocate any TxFIFO space to OUT endpoints.
+ */
+
+#ifndef CONFIG_USBDEV_RXFIFO_SIZE
+# define CONFIG_USBDEV_RXFIFO_SIZE 512
+#endif
+
+#ifndef CONFIG_USBDEV_EP0_TXFIFO_SIZE
+# define CONFIG_USBDEV_EP0_TXFIFO_SIZE 192
+#endif
+
+#ifndef CONFIG_USBDEV_EP1_TXFIFO_SIZE
+# define CONFIG_USBDEV_EP1_TXFIFO_SIZE 192
+#endif
+
+#ifndef CONFIG_USBDEV_EP2_TXFIFO_SIZE
+# define CONFIG_USBDEV_EP2_TXFIFO_SIZE 192
+#endif
+
+#ifndef CONFIG_USBDEV_EP3_TXFIFO_SIZE
+# define CONFIG_USBDEV_EP3_TXFIFO_SIZE 192
+#endif
+
+#if (CONFIG_USBDEV_RXFIFO_SIZE + CONFIG_USBDEV_EP0_TXFIFO_SIZE + \
+ CONFIG_USBDEV_EP2_TXFIFO_SIZE + CONFIG_USBDEV_EP3_TXFIFO_SIZE) > 1280
+# error "FIFO allocations exceed FIFO memory size"
+#endif
+
+/* The actual FIFO addresses that we use must be aligned to 4-byte boundaries;
+ * FIFO sizes must be provided in units of 32-bit words.
+ */
+
+#define STM32_RXFIFO_BYTES ((CONFIG_USBDEV_RXFIFO_SIZE + 3) & ~3)
+#define STM32_RXFIFO_WORDS ((CONFIG_USBDEV_RXFIFO_SIZE + 3) >> 2)
+
+#define STM32_EP0_TXFIFO_BYTES ((CONFIG_USBDEV_EP0_TXFIFO_SIZE + 3) & ~3)
+#define STM32_EP0_TXFIFO_WORDS ((CONFIG_USBDEV_EP0_TXFIFO_SIZE + 3) >> 2)
+
+#if STM32_EP0_TXFIFO_WORDS < 16 || STM32_EP0_TXFIFO_WORDS > 256
+# error "CONFIG_USBDEV_EP0_TXFIFO_SIZE is out of range"
+#endif
+
+#define STM32_EP1_TXFIFO_BYTES ((CONFIG_USBDEV_EP1_TXFIFO_SIZE + 3) & ~3)
+#define STM32_EP1_TXFIFO_WORDS ((CONFIG_USBDEV_EP1_TXFIFO_SIZE + 3) >> 2)
+
+#if STM32_EP1_TXFIFO_WORDS < 16
+# error "CONFIG_USBDEV_EP1_TXFIFO_SIZE is out of range"
+#endif
+
+#define STM32_EP2_TXFIFO_BYTES ((CONFIG_USBDEV_EP2_TXFIFO_SIZE + 3) & ~3)
+#define STM32_EP2_TXFIFO_WORDS ((CONFIG_USBDEV_EP2_TXFIFO_SIZE + 3) >> 2)
+
+#if STM32_EP2_TXFIFO_WORDS < 16
+# error "CONFIG_USBDEV_EP2_TXFIFO_SIZE is out of range"
+#endif
+
+#define STM32_EP3_TXFIFO_BYTES ((CONFIG_USBDEV_EP3_TXFIFO_SIZE + 3) & ~3)
+#define STM32_EP3_TXFIFO_WORDS ((CONFIG_USBDEV_EP3_TXFIFO_SIZE + 3) >> 2)
+
+#if STM32_EP3_TXFIFO_WORDS < 16
+# error "CONFIG_USBDEV_EP3_TXFIFO_SIZE is out of range"
+#endif
+
+/* REVISIT! This forces a hack that polls DTXFSTS for space in the Tx FIFO.
+ * Enabling this option is a BAD thing. It will cause inline waits inside
+ * of the USB interrupt handler. The correct way to handle this is to
+ * enable the correct TxFIFO interrupt and wait until the Tx FIFO is empty.
+ * Unfortunately, the interrupt driven logic is not working... Please fix!
+ */
+
+#define ENABLE_DTXFSTS_POLLHACK 1
+
+/* Debug ***********************************************************************/
+/* Trace error codes */
+
+#define STM32_TRACEERR_ALLOCFAIL 0x01
+#define STM32_TRACEERR_BADCLEARFEATURE 0x02
+#define STM32_TRACEERR_BADDEVGETSTATUS 0x03
+#define STM32_TRACEERR_BADEPNO 0x04
+#define STM32_TRACEERR_BADEPGETSTATUS 0x05
+#define STM32_TRACEERR_BADGETCONFIG 0x06
+#define STM32_TRACEERR_BADGETSETDESC 0x07
+#define STM32_TRACEERR_BADGETSTATUS 0x08
+#define STM32_TRACEERR_BADSETADDRESS 0x09
+#define STM32_TRACEERR_BADSETCONFIG 0x0a
+#define STM32_TRACEERR_BADSETFEATURE 0x0b
+#define STM32_TRACEERR_BADTESTMODE 0x0c
+#define STM32_TRACEERR_BINDFAILED 0x0d
+#define STM32_TRACEERR_DISPATCHSTALL 0x0e
+#define STM32_TRACEERR_DRIVER 0x0f
+#define STM32_TRACEERR_DRIVERREGISTERED 0x10
+#define STM32_TRACEERR_EP0NOSETUP 0x11
+#define STM32_TRACEERR_EP0SETUPSTALLED 0x12
+#define STM32_TRACEERR_EPINNULLPACKET 0x13
+#define STM32_TRACEERR_EPOUTNULLPACKET 0x14
+#define STM32_TRACEERR_INVALIDCTRLREQ 0x15
+#define STM32_TRACEERR_INVALIDPARMS 0x16
+#define STM32_TRACEERR_IRQREGISTRATION 0x17
+#define STM32_TRACEERR_NOEP 0x18
+#define STM32_TRACEERR_NOTCONFIGURED 0x19
+#define STM32_TRACEERR_EPOUTQEMPTY 0x1a
+#define STM32_TRACEERR_EPINQEMPTY 0x1b
+#define STM32_TRACEERR_NOOUTSETUP 0x1c
+
+/* Trace interrupt codes */
+
+#define STM32_TRACEINTID_USB 1 /* USB Interrupt entry/exit */
+#define STM32_TRACEINTID_INTPENDING 2 /* On each pass through the loop */
+
+#define STM32_TRACEINTID_EPOUT (10 + 0) /* First level interrupt decode */
+#define STM32_TRACEINTID_EPIN (10 + 1)
+#define STM32_TRACEINTID_MISMATCH (10 + 2)
+#define STM32_TRACEINTID_WAKEUP (10 + 3)
+#define STM32_TRACEINTID_SUSPEND (10 + 4)
+#define STM32_TRACEINTID_SOF (10 + 5)
+#define STM32_TRACEINTID_RXFIFO (10 + 6)
+#define STM32_TRACEINTID_DEVRESET (10 + 7)
+#define STM32_TRACEINTID_ENUMDNE (10 + 8)
+#define STM32_TRACEINTID_IISOIXFR (10 + 9)
+#define STM32_TRACEINTID_IISOOXFR (10 + 10)
+#define STM32_TRACEINTID_SRQ (10 + 11)
+#define STM32_TRACEINTID_OTG (10 + 12)
+
+#define STM32_TRACEINTID_EPOUT_XFRC (40 + 0) /* EPOUT second level decode */
+#define STM32_TRACEINTID_EPOUT_EPDISD (40 + 1)
+#define STM32_TRACEINTID_EPOUT_SETUP (40 + 2)
+#define STM32_TRACEINTID_DISPATCH (40 + 3)
+
+#define STM32_TRACEINTID_GETSTATUS (50 + 0) /* EPOUT third level decode */
+#define STM32_TRACEINTID_EPGETSTATUS (50 + 1)
+#define STM32_TRACEINTID_DEVGETSTATUS (50 + 2)
+#define STM32_TRACEINTID_IFGETSTATUS (50 + 3)
+#define STM32_TRACEINTID_CLEARFEATURE (50 + 4)
+#define STM32_TRACEINTID_SETFEATURE (50 + 5)
+#define STM32_TRACEINTID_SETADDRESS (50 + 6)
+#define STM32_TRACEINTID_GETSETDESC (50 + 7)
+#define STM32_TRACEINTID_GETCONFIG (50 + 8)
+#define STM32_TRACEINTID_SETCONFIG (50 + 9)
+#define STM32_TRACEINTID_GETSETIF (50 + 10)
+#define STM32_TRACEINTID_SYNCHFRAME (50 + 11)
+
+#define STM32_TRACEINTID_EPIN_XFRC (70 + 0) /* EPIN second level decode */
+#define STM32_TRACEINTID_EPIN_TOC (70 + 1)
+#define STM32_TRACEINTID_EPIN_ITTXFE (70 + 2)
+#define STM32_TRACEINTID_EPIN_EPDISD (70 + 3)
+#define STM32_TRACEINTID_EPIN_TXFE (70 + 4)
+
+#define STM32_TRACEINTID_EPIN_EMPWAIT (80 + 0) /* EPIN second level decode */
+
+#define STM32_TRACEINTID_OUTNAK (90 + 0) /* RXFLVL second level decode */
+#define STM32_TRACEINTID_OUTRECVD (90 + 1)
+#define STM32_TRACEINTID_OUTDONE (90 + 2)
+#define STM32_TRACEINTID_SETUPDONE (90 + 3)
+#define STM32_TRACEINTID_SETUPRECVD (90 + 4)
+
+/* Endpoints ******************************************************************/
+
+/* Number of endpoints */
+
+#define STM32_NENDPOINTS (4) /* ep0-3 x 2 for IN and OUT */
+
+/* Odd physical endpoint numbers are IN; even are OUT */
+
+#define STM32_EPPHYIN2LOG(epphy) ((uint8_t)(epphy)|USB_DIR_IN)
+#define STM32_EPPHYOUT2LOG(epphy) ((uint8_t)(epphy)|USB_DIR_OUT)
+
+/* Endpoint 0 */
+
+#define EP0 (0)
+
+/* The set of all enpoints available to the class implementation (1-3) */
+
+#define STM32_EP_AVAILABLE (0x0e) /* All available endpoints */
+
+/* Maximum packet sizes for full speed endpoints */
+
+#define STM32_MAXPACKET (64) /* Max packet size (1-64) */
+
+/* Delays **********************************************************************/
+
+#define STM32_READY_DELAY 200000
+#define STM32_FLUSH_DELAY 200000
+
+/* Request queue operations ****************************************************/
+
+#define stm32_rqempty(ep) ((ep)->head == NULL)
+#define stm32_rqpeek(ep) ((ep)->head)
+
+/* Standard stuff **************************************************************/
+
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/*******************************************************************************
+ * Private Types
+ *******************************************************************************/
+
+/* Overall device state */
+
+enum stm32_devstate_e
+{
+ DEVSTATE_DEFAULT = 0, /* Power-up, unconfigured state. This state simply
+ * means that the device is not yet been given an
+ * address.
+ * SET: At initialization, uninitialization,
+ * reset, and whenever the device address
+ * is set to zero
+ * TESTED: Never
+ */
+ DEVSTATE_ADDRESSED, /* Device address has been assigned, not no
+ * configuration has yet been selected.
+ * SET: When either a non-zero device address
+ * is first assigned or when the device
+ * is unconfigured (with configuration == 0)
+ * TESTED: never
+ */
+ DEVSTATE_CONFIGURED, /* Address assigned and configured:
+ * SET: When the device has been addressed and
+ * an non-zero configuration has been selected.
+ * TESTED: In many places to assure that the USB device
+ * has been properly configured by the host.
+ */
+};
+
+/* Endpoint 0 states */
+
+enum stm32_ep0state_e
+{
+ EP0STATE_IDLE = 0, /* Idle State, leave on receiving a SETUP packet or
+ * epsubmit:
+ * SET: In stm32_epin() and stm32_epout() when
+ * we revert from request processing to
+ * SETUP processing.
+ * TESTED: Never
+ */
+ EP0STATE_SETUP_OUT, /* OUT SETUP packet received. Waiting for the DATA
+ * OUT phase of SETUP Packet to complete before
+ * processing a SETUP command (without a USB request):
+ * SET: Set in stm32_rxinterrupt() when SETUP OUT
+ * packet is received.
+ * TESTED: In stm32_ep0out_receive()
+ */
+ EP0STATE_SETUP_READY, /* IN SETUP packet received -OR- OUT SETUP packet and
+ * accompanying data have been received. Processing
+ * of SETUP command will happen soon.
+ * SET: (1) stm32_ep0out_receive() when the OUT
+ * SETUP data phase completes, or (2)
+ * stm32_rxinterrupt() when an IN SETUP is
+ * packet received.
+ * TESTED: Tested in stm32_epout_interrupt() when
+ * SETUP phase is done to see if the SETUP
+ * command is ready to be processed. Also
+ * tested in stm32_ep0out_setup() just to
+ * double-check that we have a SETUP request
+ * and any accompanying data.
+ */
+ EP0STATE_SETUP_PROCESS, /* SETUP Packet is being processed by stm32_ep0out_setup():
+ * SET: When SETUP packet received in EP0 OUT
+ * TESTED: Never
+ */
+ EP0STATE_SETUPRESPONSE, /* Short SETUP response write (without a USB request):
+ * SET: When SETUP response is sent by
+ * stm32_ep0in_setupresponse()
+ * TESTED: Never
+ */
+ EP0STATE_DATA_IN, /* Waiting for data out stage (with a USB request):
+ * SET: In stm32_epin_request() when a write
+ * request is processed on EP0.
+ * TESTED: In stm32_epin() to see if we should
+ * revert to SETUP processing.
+ */
+ EP0STATE_DATA_OUT /* Waiting for data in phase to complete ( with a
+ * USB request)
+ * SET: In stm32_epout_request() when a read
+ * request is processed on EP0.
+ * TESTED: In stm32_epout() to see if we should
+ * revert to SETUP processing
+ */
+};
+
+/* Parsed control request */
+
+struct stm32_ctrlreq_s
+{
+ uint8_t type;
+ uint8_t req;
+ uint16_t value;
+ uint16_t index;
+ uint16_t len;
+};
+
+/* A container for a request so that the request may be retained in a list */
+
+struct stm32_req_s
+{
+ struct usbdev_req_s req; /* Standard USB request */
+ struct stm32_req_s *flink; /* Supports a singly linked list */
+};
+
+/* This is the internal representation of an endpoint */
+
+struct stm32_ep_s
+{
+ /* Common endpoint fields. This must be the first thing defined in the
+ * structure so that it is possible to simply cast from struct usbdev_ep_s
+ * to struct stm32_ep_s.
+ */
+
+ struct usbdev_ep_s ep; /* Standard endpoint structure */
+
+ /* STM32-specific fields */
+
+ struct stm32_usbdev_s *dev; /* Reference to private driver data */
+ struct stm32_req_s *head; /* Request list for this endpoint */
+ struct stm32_req_s *tail;
+ uint8_t epphy; /* Physical EP address */
+ uint8_t eptype:2; /* Endpoint type */
+ uint8_t configured:1; /* 1: Endpoint has been configured */
+ uint8_t active:1; /* 1: A request is being processed */
+ uint8_t stalled:1; /* 1: Endpoint is stalled */
+ uint8_t isin:1; /* 1: IN Endpoint */
+ uint8_t odd:1; /* 1: Odd frame */
+ uint8_t zlp:1; /* 1: Transmit a zero-length-packet (IN EPs only) */
+};
+
+/* This structure retains the state of the USB device controller */
+
+struct stm32_usbdev_s
+{
+ /* Common device fields. This must be the first thing defined in the
+ * structure so that it is possible to simply cast from struct usbdev_s
+ * to struct stm32_usbdev_s.
+ */
+
+ struct usbdev_s usbdev;
+
+ /* The bound device class driver */
+
+ struct usbdevclass_driver_s *driver;
+
+ /* STM32-specific fields */
+
+ uint8_t stalled:1; /* 1: Protocol stalled */
+ uint8_t selfpowered:1; /* 1: Device is self powered */
+ uint8_t connected:1; /* 1: Host connected */
+ uint8_t addressed:1; /* 1: Peripheral address has been set */
+ uint8_t configured:1; /* 1: Class driver has been configured */
+ uint8_t wakeup:1; /* 1: Device remote wake-up */
+ uint8_t dotest:1; /* 1: Test mode selected */
+
+ uint8_t devstate:4; /* See enum stm32_devstate_e */
+ uint8_t ep0state:4; /* See enum stm32_ep0state_e */
+ uint8_t testmode:4; /* Selected test mode */
+ uint8_t epavail:4; /* Bitset of available endpoints */
+
+ /* E0 SETUP data buffering.
+ *
+ * ctrlreq:
+ * The 8-byte SETUP request is received on the EP0 OUT endpoint and is
+ * saved.
+ *
+ * ep0data
+ * For OUT SETUP requests, the SETUP data phase must also complete before
+ * the SETUP command can be processed. The pack receipt logic will save
+ * the accompanying EP0 IN data in ep0data[] before the SETUP command is
+ * processed.
+ *
+ * For IN SETUP requests, the DATA phase will occurr AFTER the SETUP
+ * control request is processed. In that case, ep0data[] may be used as
+ * the response buffer.
+ *
+ * ep0datlen
+ * Lenght of OUT DATA received in ep0data[] (Not used with OUT data)
+ */
+
+ struct usb_ctrlreq_s ctrlreq;
+ uint8_t ep0data[CONFIG_USBDEV_SETUP_MAXDATASIZE];
+ uint16_t ep0datlen;
+
+ /* The endpoint lists */
+
+ struct stm32_ep_s epin[STM32_NENDPOINTS];
+ struct stm32_ep_s epout[STM32_NENDPOINTS];
+};
+
+/*******************************************************************************
+ * Private Function Prototypes
+ *******************************************************************************/
+
+/* Register operations ********************************************************/
+
+#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint32_t stm32_getreg(uint32_t addr);
+static void stm32_putreg(uint32_t val, uint32_t addr);
+#else
+# define stm32_getreg(addr) getreg32(addr)
+# define stm32_putreg(val,addr) putreg32(val,addr)
+#endif
+
+/* Request queue operations ****************************************************/
+
+static FAR struct stm32_req_s *stm32_req_remfirst(FAR struct stm32_ep_s *privep);
+static bool stm32_req_addlast(FAR struct stm32_ep_s *privep,
+ FAR struct stm32_req_s *req);
+
+/* Low level data transfers and request operations *****************************/
+/* Special endpoint 0 data transfer logic */
+
+static void stm32_ep0in_setupresponse(FAR struct stm32_usbdev_s *priv,
+ FAR uint8_t *data, uint32_t nbytes);
+static inline void stm32_ep0in_transmitzlp(FAR struct stm32_usbdev_s *priv);
+static void stm32_ep0in_activate(void);
+
+static void stm32_ep0out_ctrlsetup(FAR struct stm32_usbdev_s *priv);
+
+/* IN request and TxFIFO handling */
+
+static void stm32_txfifo_write(FAR struct stm32_ep_s *privep,
+ FAR uint8_t *buf, int nbytes);
+static void stm32_epin_transfer(FAR struct stm32_ep_s *privep,
+ FAR uint8_t *buf, int nbytes);
+static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
+ FAR struct stm32_ep_s *privep);
+
+/* OUT request and RxFIFO handling */
+
+static void stm32_rxfifo_read(FAR struct stm32_ep_s *privep,
+ FAR uint8_t *dest, uint16_t len);
+static void stm32_rxfifo_discard(FAR struct stm32_ep_s *privep, int len);
+static void stm32_epout_complete(FAR struct stm32_usbdev_s *priv,
+ FAR struct stm32_ep_s *privep);
+static inline void stm32_ep0out_receive(FAR struct stm32_ep_s *privep, int bcnt);
+static inline void stm32_epout_receive(FAR struct stm32_ep_s *privep, int bcnt);
+static void stm32_epout_request(FAR struct stm32_usbdev_s *priv,
+ FAR struct stm32_ep_s *privep);
+
+/* General request handling */
+
+static void stm32_ep_flush(FAR struct stm32_ep_s *privep);
+static void stm32_req_complete(FAR struct stm32_ep_s *privep,
+ int16_t result);
+static void stm32_req_cancel(FAR struct stm32_ep_s *privep,
+ int16_t status);
+
+/* Interrupt handling **********************************************************/
+
+static struct stm32_ep_s *stm32_ep_findbyaddr(struct stm32_usbdev_s *priv,
+ uint16_t eplog);
+static int stm32_req_dispatch(FAR struct stm32_usbdev_s *priv,
+ FAR const struct usb_ctrlreq_s *ctrl);
+static void stm32_usbreset(FAR struct stm32_usbdev_s *priv);
+
+/* Second level OUT endpoint interrupt processing */
+
+static inline void stm32_ep0out_testmode(FAR struct stm32_usbdev_s *priv,
+ uint16_t index);
+static inline void stm32_ep0out_stdrequest(struct stm32_usbdev_s *priv,
+ FAR struct stm32_ctrlreq_s *ctrlreq);
+static inline void stm32_ep0out_setup(struct stm32_usbdev_s *priv);
+static inline void stm32_epout(FAR struct stm32_usbdev_s *priv,
+ uint8_t epno);
+static inline void stm32_epout_interrupt(FAR struct stm32_usbdev_s *priv);
+
+/* Second level IN endpoint interrupt processing */
+
+static inline void stm32_epin_runtestmode(FAR struct stm32_usbdev_s *priv);
+static inline void stm32_epin(FAR struct stm32_usbdev_s *priv, uint8_t epno);
+static inline void stm32_epin_txfifoempty(FAR struct stm32_usbdev_s *priv, int epno);
+static inline void stm32_epin_interrupt(FAR struct stm32_usbdev_s *priv);
+
+/* Other second level interrupt processing */
+
+static inline void stm32_resumeinterrupt(FAR struct stm32_usbdev_s *priv);
+static inline void stm32_suspendinterrupt(FAR struct stm32_usbdev_s *priv);
+static inline void stm32_rxinterrupt(FAR struct stm32_usbdev_s *priv);
+static inline void stm32_enuminterrupt(FAR struct stm32_usbdev_s *priv);
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+static inline void stm32_isocininterrupt(FAR struct stm32_usbdev_s *priv);
+static inline void stm32_isocoutinterrupt(FAR struct stm32_usbdev_s *priv);
+#endif
+#ifdef CONFIG_USBDEV_VBUSSENSING
+static inline void stm32_sessioninterrupt(FAR struct stm32_usbdev_s *priv);
+static inline void stm32_otginterrupt(FAR struct stm32_usbdev_s *priv);
+#endif
+
+/* First level interrupt processing */
+
+static int stm32_usbinterrupt(int irq, FAR void *context);
+
+/* Endpoint operations *********************************************************/
+/* Global OUT NAK controls */
+
+static void stm32_enablegonak(FAR struct stm32_ep_s *privep);
+static void stm32_disablegonak(FAR struct stm32_ep_s *privep);
+
+/* Endpoint configuration */
+
+static int stm32_epout_configure(FAR struct stm32_ep_s *privep,
+ uint8_t eptype, uint16_t maxpacket);
+static int stm32_epin_configure(FAR struct stm32_ep_s *privep,
+ uint8_t eptype, uint16_t maxpacket);
+static int stm32_ep_configure(FAR struct usbdev_ep_s *ep,
+ FAR const struct usb_epdesc_s *desc, bool last);
+static void stm32_ep0_configure(FAR struct stm32_usbdev_s *priv);
+
+/* Endpoint disable */
+
+static void stm32_epout_disable(FAR struct stm32_ep_s *privep);
+static void stm32_epin_disable(FAR struct stm32_ep_s *privep);
+static int stm32_ep_disable(FAR struct usbdev_ep_s *ep);
+
+/* Endpoint request management */
+
+static FAR struct usbdev_req_s *stm32_ep_allocreq(FAR struct usbdev_ep_s *ep);
+static void stm32_ep_freereq(FAR struct usbdev_ep_s *ep,
+ FAR struct usbdev_req_s *);
+
+/* Endpoint buffer management */
+
+#ifdef CONFIG_ARCH_USBDEV_DMA
+static void *stm32_ep_allocbuffer(FAR struct usbdev_ep_s *ep, unsigned bytes);
+static void stm32_ep_freebuffer(FAR struct usbdev_ep_s *ep, FAR void *buf);
+#endif
+
+/* Endpoint request submission */
+
+static int stm32_ep_submit(FAR struct usbdev_ep_s *ep,
+ struct usbdev_req_s *req);
+
+/* Endpoint request cancellation */
+
+static int stm32_ep_cancel(FAR struct usbdev_ep_s *ep,
+ struct usbdev_req_s *req);
+
+/* Stall handling */
+
+static int stm32_epout_setstall(FAR struct stm32_ep_s *privep);
+static int stm32_epin_setstall(FAR struct stm32_ep_s *privep);
+static int stm32_ep_setstall(FAR struct stm32_ep_s *privep);
+static int stm32_ep_clrstall(FAR struct stm32_ep_s *privep);
+static int stm32_ep_stall(FAR struct usbdev_ep_s *ep, bool resume);
+static void stm32_ep0_stall(FAR struct stm32_usbdev_s *priv);
+
+/* Endpoint allocation */
+
+static FAR struct usbdev_ep_s *stm32_ep_alloc(FAR struct usbdev_s *dev,
+ uint8_t epno, bool in, uint8_t eptype);
+static void stm32_ep_free(FAR struct usbdev_s *dev,
+ FAR struct usbdev_ep_s *ep);
+
+/* USB device controller operations ********************************************/
+
+static int stm32_getframe(struct usbdev_s *dev);
+static int stm32_wakeup(struct usbdev_s *dev);
+static int stm32_selfpowered(struct usbdev_s *dev, bool selfpowered);
+static int stm32_pullup(struct usbdev_s *dev, bool enable);
+static void stm32_setaddress(struct stm32_usbdev_s *priv,
+ uint16_t address);
+static int stm32_txfifo_flush(uint32_t txfnum);
+static int stm32_rxfifo_flush(void);
+
+/* Initialization **************************************************************/
+
+static void stm32_swinitialize(FAR struct stm32_usbdev_s *priv);
+static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv);
+
+/*******************************************************************************
+ * Private Data
+ *******************************************************************************/
+/* Since there is only a single USB interface, all status information can be
+ * be simply retained in a single global instance.
+ */
+
+static struct stm32_usbdev_s g_otgfsdev;
+
+static const struct usbdev_epops_s g_epops =
+{
+ .configure = stm32_ep_configure,
+ .disable = stm32_ep_disable,
+ .allocreq = stm32_ep_allocreq,
+ .freereq = stm32_ep_freereq,
+#ifdef CONFIG_ARCH_USBDEV_DMA
+ .allocbuffer = stm32_ep_allocbuffer,
+ .freebuffer = stm32_ep_freebuffer,
+#endif
+ .submit = stm32_ep_submit,
+ .cancel = stm32_ep_cancel,
+ .stall = stm32_ep_stall,
+};
+
+static const struct usbdev_ops_s g_devops =
+{
+ .allocep = stm32_ep_alloc,
+ .freeep = stm32_ep_free,
+ .getframe = stm32_getframe,
+ .wakeup = stm32_wakeup,
+ .selfpowered = stm32_selfpowered,
+ .pullup = stm32_pullup,
+};
+
+/*******************************************************************************
+ * Public Data
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Private Functions
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: stm32_getreg
+ *
+ * Description:
+ * Get the contents of an STM32 register
+ *
+ *******************************************************************************/
+
+#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint32_t stm32_getreg(uint32_t addr)
+{
+ static uint32_t prevaddr = 0;
+ static uint32_t preval = 0;
+ static uint32_t count = 0;
+
+ /* Read the value from the register */
+
+ uint32_t val = getreg32(addr);
+
+ /* Is this the same value that we read from the same registe last time? Are
+ * we polling the register? If so, suppress some of the output.
+ */
+
+ if (addr == prevaddr && val == preval)
+ {
+ if (count == 0xffffffff || ++count > 3)
+ {
+ if (count == 4)
+ {
+ lldbg("...\n");
+ }
+ return val;
+ }
+ }
+
+ /* No this is a new address or value */
+
+ else
+ {
+ /* Did we print "..." for the previous value? */
+
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
+
+ lldbg("[repeats %d more times]\n", count-3);
+ }
+
+ /* Save the new address, value, and count */
+
+ prevaddr = addr;
+ preval = val;
+ count = 1;
+ }
+
+ /* Show the register value read */
+
+ lldbg("%08x->%08x\n", addr, val);
+ return val;
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_putreg
+ *
+ * Description:
+ * Set the contents of an STM32 register to a value
+ *
+ *******************************************************************************/
+
+#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static void stm32_putreg(uint32_t val, uint32_t addr)
+{
+ /* Show the register value being written */
+
+ lldbg("%08x<-%08x\n", addr, val);
+
+ /* Write the value */
+
+ putreg32(val, addr);
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_req_remfirst
+ *
+ * Description:
+ * Remove a request from the head of an endpoint request queue
+ *
+ *******************************************************************************/
+
+static FAR struct stm32_req_s *stm32_req_remfirst(FAR struct stm32_ep_s *privep)
+{
+ FAR struct stm32_req_s *ret = privep->head;
+
+ if (ret)
+ {
+ privep->head = ret->flink;
+ if (!privep->head)
+ {
+ privep->tail = NULL;
+ }
+
+ ret->flink = NULL;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_req_addlast
+ *
+ * Description:
+ * Add a request to the end of an endpoint request queue
+ *
+ *******************************************************************************/
+
+static bool stm32_req_addlast(FAR struct stm32_ep_s *privep,
+ FAR struct stm32_req_s *req)
+{
+ bool is_empty = !privep->head;
+
+ req->flink = NULL;
+ if (is_empty)
+ {
+ privep->head = req;
+ privep->tail = req;
+ }
+ else
+ {
+ privep->tail->flink = req;
+ privep->tail = req;
+ }
+ return is_empty;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep0in_setupresponse
+ *
+ * Description:
+ * Schedule a short transfer on Endpoint 0 (IN or OUT)
+ *
+ *******************************************************************************/
+
+static void stm32_ep0in_setupresponse(FAR struct stm32_usbdev_s *priv,
+ FAR uint8_t *buf, uint32_t nbytes)
+{
+ stm32_epin_transfer(&priv->epin[EP0], buf, nbytes);
+ priv->ep0state = EP0STATE_SETUPRESPONSE;
+ stm32_ep0out_ctrlsetup(priv);
+}
+
+/****************************************************************************
+ * Name: stm32_ep0in_transmitzlp
+ *
+ * Description:
+ * Send a zero length packet (ZLP) on endpoint 0 IN
+ *
+ ****************************************************************************/
+
+static inline void stm32_ep0in_transmitzlp(FAR struct stm32_usbdev_s *priv)
+{
+ stm32_ep0in_setupresponse(priv, NULL, 0);
+}
+
+/*******************************************************************************
+ * Name: stm32_ep0in_activate
+ *
+ * Description:
+ * Activate the endpoint 0 IN endpoint.
+ *
+ *******************************************************************************/
+
+static void stm32_ep0in_activate(void)
+{
+ uint32_t regval;
+
+ /* Set the max packet size of the IN EP. */
+
+ regval = stm32_getreg(STM32_OTGFS_DIEPCTL0);
+ regval &= ~OTGFS_DIEPCTL0_MPSIZ_MASK;
+
+#if CONFIG_USBDEV_EP0_MAXSIZE == 8
+ regval |= OTGFS_DIEPCTL0_MPSIZ_8;
+#elif CONFIG_USBDEV_EP0_MAXSIZE == 16
+ regval |= OTGFS_DIEPCTL0_MPSIZ_16;
+#elif CONFIG_USBDEV_EP0_MAXSIZE == 32
+ regval |= OTGFS_DIEPCTL0_MPSIZ_32;
+#elif CONFIG_USBDEV_EP0_MAXSIZE == 64
+ regval |= OTGFS_DIEPCTL0_MPSIZ_64;
+#else
+# error "Unsupported value of CONFIG_USBDEV_EP0_MAXSIZE"
+#endif
+
+ stm32_putreg(regval, STM32_OTGFS_DIEPCTL0);
+
+ /* Clear global IN NAK */
+
+ regval = stm32_getreg(STM32_OTGFS_DCTL);
+ regval |= OTGFS_DCTL_CGINAK;
+ stm32_putreg(regval, STM32_OTGFS_DCTL);
+}
+
+/*******************************************************************************
+ * Name: stm32_ep0out_ctrlsetup
+ *
+ * Description:
+ * Setup to receive a SETUP packet.
+ *
+ *******************************************************************************/
+
+static void stm32_ep0out_ctrlsetup(FAR struct stm32_usbdev_s *priv)
+{
+ uint32_t regval;
+
+ /* Setup the hardware to perform the SETUP transfer */
+
+ regval = (USB_SIZEOF_CTRLREQ * 3 << OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT) |
+ (OTGFS_DOEPTSIZ0_PKTCNT) |
+ (3 << OTGFS_DOEPTSIZ0_STUPCNT_SHIFT);
+ stm32_putreg(regval, STM32_OTGFS_DOEPTSIZ0);
+
+ /* Then clear NAKing and enable the transfer */
+
+ regval = stm32_getreg(STM32_OTGFS_DOEPCTL0);
+ regval |= (OTGFS_DOEPCTL0_CNAK | OTGFS_DOEPCTL0_EPENA);
+ stm32_putreg(regval, STM32_OTGFS_DOEPCTL0);
+}
+
+/****************************************************************************
+ * Name: stm32_txfifo_write
+ *
+ * Description:
+ * Send data to the endpoint's TxFIFO.
+ *
+ ****************************************************************************/
+
+static void stm32_txfifo_write(FAR struct stm32_ep_s *privep,
+ FAR uint8_t *buf, int nbytes)
+{
+ uint32_t regaddr;
+ uint32_t regval;
+ int nwords;
+ int i;
+
+ /* Convert the number of bytes to words */
+
+ nwords = (nbytes + 3) >> 2;
+
+ /* Get the TxFIFO for this endpoint (same as the endpoint number) */
+
+ regaddr = STM32_OTGFS_DFIFO_DEP(privep->epphy);
+
+ /* Then transfer each word to the TxFIFO */
+
+ for (i = 0; i < nwords; i++)
+ {
+ /* Read four bytes from the source buffer (to avoid unaligned accesses)
+ * and pack these into one 32-bit word (little endian).
+ */
+
+ regval = (uint32_t)*buf++;
+ regval |= ((uint32_t)*buf++) << 8;
+ regval |= ((uint32_t)*buf++) << 16;
+ regval |= ((uint32_t)*buf++) << 24;
+
+ /* Then write the packed data to the TxFIFO */
+
+ stm32_putreg(regval, regaddr);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_epin_transfer
+ *
+ * Description:
+ * Start the Tx data transfer
+ *
+ ****************************************************************************/
+
+static void stm32_epin_transfer(FAR struct stm32_ep_s *privep,
+ FAR uint8_t *buf, int nbytes)
+{
+ uint32_t pktcnt;
+ uint32_t regval;
+
+ /* Read the DIEPSIZx register */
+
+ regval = stm32_getreg(STM32_OTGFS_DIEPTSIZ(privep->epphy));
+
+ /* Clear the XFRSIZ, PKTCNT, and MCNT field of the DIEPSIZx register */
+
+ regval &= ~(OTGFS_DIEPTSIZ_XFRSIZ_MASK | OTGFS_DIEPTSIZ_PKTCNT_MASK |
+ OTGFS_DIEPTSIZ_MCNT_MASK);
+
+ /* Are we sending a zero length packet (ZLP) */
+
+ if (nbytes == 0)
+ {
+ /* Yes.. leave the transfer size at zero and set the packet count to 1 */
+
+ pktcnt = 1;
+ }
+ else
+ {
+ /* No.. Program the transfer size and packet count . First calculate:
+ *
+ * xfrsize = The total number of bytes to be sent.
+ * pktcnt = the number of packets (of maxpacket bytes) required to
+ * perform the transfer.
+ */
+
+ pktcnt = ((uint32_t)nbytes + (privep->ep.maxpacket - 1)) / privep->ep.maxpacket;
+ }
+
+ /* Set the XFRSIZ and PKTCNT */
+
+ regval |= (pktcnt << OTGFS_DIEPTSIZ_PKTCNT_SHIFT);
+ regval |= ((uint32_t)nbytes << OTGFS_DIEPTSIZ_XFRSIZ_SHIFT);
+
+ /* If this is an isconchronous endpoint, then set the multi-count field to
+ * the PKTCNT as well.
+ */
+
+ if (privep->eptype == USB_EP_ATTR_XFER_ISOC)
+ {
+ regval |= (pktcnt << OTGFS_DIEPTSIZ_MCNT_SHIFT);
+ }
+
+ /* Save DIEPSIZx register value */
+
+ stm32_putreg(regval, STM32_OTGFS_DIEPTSIZ(privep->epphy));
+
+ /* Read the DIEPCTLx register */
+
+ regval = stm32_getreg(STM32_OTGFS_DIEPCTL(privep->epphy));
+
+ /* If this is an isochronous endpoint, then set the even/odd frame bit
+ * the DIEPCTLx register.
+ */
+
+ if (privep->eptype == USB_EP_ATTR_XFER_ISOC)
+ {
+ /* Check bit 0 of the frame number of the received SOF and set the
+ * even/odd frame to match.
+ */
+
+ uint32_t status = stm32_getreg(STM32_OTGFS_DSTS);
+ if ((status & OTGFS_DSTS_SOFFN0) == OTGFS_DSTS_SOFFN_EVEN)
+ {
+ regval |= OTGFS_DIEPCTL_SEVNFRM;
+ }
+ else
+ {
+ regval |= OTGFS_DIEPCTL_SODDFRM;
+ }
+ }
+
+ /* EP enable, IN data in FIFO */
+
+ regval &= ~OTGFS_DIEPCTL_EPDIS;
+ regval |= (OTGFS_DIEPCTL_CNAK | OTGFS_DIEPCTL_EPENA);
+ stm32_putreg(regval, STM32_OTGFS_DIEPCTL(privep->epphy));
+
+ /* Transfer the data to the TxFIFO. At this point, the caller has already
+ * assured that there is sufficient space in the TxFIFO to hold the transfer
+ * we can just blindly continue.
+ */
+
+ stm32_txfifo_write(privep, buf, nbytes);
+}
+
+/****************************************************************************
+ * Name: stm32_epin_request
+ *
+ * Description:
+ * Begin or continue write request processing.
+ *
+ ****************************************************************************/
+
+static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
+ FAR struct stm32_ep_s *privep)
+{
+ struct stm32_req_s *privreq;
+ uint32_t regaddr;
+ uint32_t regval;
+#ifdef ENABLE_DTXFSTS_POLLHACK
+ int32_t timeout;
+#endif
+ uint8_t *buf;
+ int nbytes;
+ int nwords;
+ int bytesleft;
+
+ /* We get here in one of four possible ways. From three interrupting
+ * events:
+ *
+ * 1. From stm32_epin as part of the transfer complete interrupt processing
+ * This interrupt indicates that the last transfer has completed.
+ * 2. As part of the ITTXFE interrupt processing. That interrupt indicates
+ * that an IN token was received when the associated TxFIFO was empty.
+ * 3. From stm32_epin_txfifoempty as part of the TXFE interrupt processing.
+ * The TXFE interrupt is only enabled when the TxFIFO is full and the
+ * software must wait for space to become available in the TxFIFO.
+ *
+ * And this function may be called immediately when the write request is
+ * queue to start up the next transaction.
+ *
+ * 4. From stm32_ep_submit when a new write request is received WHILE the
+ * endpoint is not active (privep->active == false).
+ */
+
+ /* Check the request from the head of the endpoint request queue */
+
+ privreq = stm32_rqpeek(privep);
+ if (!privreq)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPINQEMPTY), privep->epphy);
+
+ /* There is no TX transfer in progress and no new pending TX
+ * requests to send. To stop transmitting any data on a particular
+ * IN endpoint, the application must set the IN NAK bit. To set this
+ * bit, the following field must be programmed.
+ */
+
+ regaddr = STM32_OTGFS_DIEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ regval |= OTGFS_DIEPCTL_SNAK;
+ stm32_putreg(regval, regaddr);
+
+ /* The endpoint is no longer active */
+
+ privep->active = false;
+ return;
+ }
+
+ ullvdbg("EP%d req=%p: len=%d xfrd=%d zlp=%d\n",
+ privep->epphy, privreq, privreq->req.len,
+ privreq->req.xfrd, privep->zlp);
+
+ /* Check for a special case: If we are just starting a request (xfrd==0) and
+ * the class driver is trying to send a zero-length packet (len==0). Then set
+ * the ZLP flag so that the packet will be sent.
+ */
+
+ if (privreq->req.len == 0)
+ {
+ /* The ZLP flag is set TRUE whenever we want to force the driver to
+ * send a zero-length-packet on the next pass through the loop (below).
+ * The flag is cleared whenever a packet is sent in the loop below.
+ */
+
+ privep->zlp = true;
+ }
+
+ /* Loop while there are still bytes to be transferred (or a zero-length-
+ * packet, ZLP, to be sent). The loop will also be terminated if there
+ * is insufficient space remaining in the TxFIFO to send a complete
+ * packet.
+ */
+
+ while (privreq->req.xfrd < privreq->req.len || privep->zlp)
+ {
+ /* Get the number of bytes left to be sent in the request */
+
+ bytesleft = privreq->req.len - privreq->req.xfrd;
+ nbytes = bytesleft;
+
+ /* Assume no zero-length-packet on the next pass through this loop */
+
+ privep->zlp = false;
+
+ /* Limit the size of the transfer to one full packet and handle
+ * zero-length packets (ZLPs).
+ */
+
+ if (nbytes > 0)
+ {
+ /* Either send the maxpacketsize or all of the remaining data in
+ * the request.
+ */
+
+ if (nbytes >= privep->ep.maxpacket)
+ {
+ nbytes = privep->ep.maxpacket;
+
+ /* Handle the case where this packet is exactly the
+ * maxpacketsize. Do we need to send a zero-length packet
+ * in this case?
+ */
+
+ if (bytesleft == privep->ep.maxpacket &&
+ (privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0)
+ {
+ /* The ZLP flag is set TRUE whenever we want to force
+ * the driver to send a zero-length-packet on the next
+ * pass through this loop. The flag is cleared (above)
+ * whenever we are committed to sending any packet and
+ * set here when we want to force one more pass through
+ * the loop.
+ */
+
+ privep->zlp = true;
+ }
+ }
+ }
+
+ /* Get the transfer size in 32-bit words */
+
+ nwords = (nbytes + 3) >> 2;
+
+ /* Get the number of 32-bit words available in the TxFIFO. The
+ * DXTFSTS indicates the amount of free space available in the
+ * endpoint TxFIFO. Values are in terms of 32-bit words:
+ *
+ * 0: Endpoint TxFIFO is full
+ * 1: 1 word available
+ * 2: 2 words available
+ * n: n words available
+ */
+
+ regaddr = STM32_OTGFS_DTXFSTS(privep->epphy);
+
+#ifdef ENABLE_DTXFSTS_POLLHACK
+ /* If ENABLE_DTXFSTS_POLLHACK is enabled , then poll DTXFSTS until
+ * space in the TxFIFO is available. If it doesn't become available,
+ * in a reasonable amount of time, then just pretend that it is.
+ */
+
+ for (timeout = 250000; timeout > 0; timeout--)
+ {
+ regval = stm32_getreg(regaddr);
+ if ((regval & OTGFS_DTXFSTS_MASK) >= nwords)
+ {
+ break;
+ }
+ }
+#else
+ /* If ENABLE_DTXFSTS_POLLHACK is not enabled, then check once for
+ * space in the TxFIFO. If space in the TxFIFO is not available,
+ * then set up an interrupt to resume the transfer when the TxFIFO
+ * is empty.
+ */
+
+ regval = stm32_getreg(regaddr);
+ if ((regval & OTGFS_DTXFSTS_MASK) < nwords)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_EMPWAIT), (uint16_t)regval);
+
+ /* There is insufficent space in the TxFIFO. Wait for a TxFIFO
+ * empty interrupt and try again.
+ */
+
+ uint32_t empmsk = stm32_getreg(STM32_OTGFS_DIEPEMPMSK);
+ empmsk |= OTGFS_DIEPEMPMSK(privep->epphy);
+ stm32_putreg(empmsk, STM32_OTGFS_DIEPEMPMSK);
+
+ /* Terminate the transfer loop */
+
+ break;
+ }
+#endif
+
+ /* Transfer data to the TxFIFO */
+
+ buf = privreq->req.buf + privreq->req.xfrd;
+ stm32_epin_transfer(privep, buf, nbytes);
+
+ /* If it was not before, the OUT endpoint is now actively transferring
+ * data.
+ */
+
+ privep->active = true;
+
+ /* EP0 is a special case */
+
+ if (privep->epphy == EP0)
+ {
+ priv->ep0state = EP0STATE_DATA_IN;
+ }
+
+ /* Update for the next time through the loop */
+
+ privreq->req.xfrd += nbytes;
+ }
+
+ /* Note that the ZLP, if any, must be sent as a separate transfer. The need
+ * for a ZLP is indicated by privep->zlp. If all of the bytes were sent
+ * (including any final null packet) then we are finished with the transfer
+ */
+
+ if (privreq->req.xfrd >= privreq->req.len && !privep->zlp)
+ {
+ usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
+ stm32_req_complete(privep, OK);
+
+ /* The endpoint is no longer transferring data */
+
+ privep->active = false;
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_rxfifo_read
+ *
+ * Description:
+ * Read packet from the RxFIFO into a read request.
+ *
+ *******************************************************************************/
+
+static void stm32_rxfifo_read(FAR struct stm32_ep_s *privep,
+ FAR uint8_t *dest, uint16_t len)
+{
+ uint32_t regaddr;
+ int i;
+
+ /* Get the address of the RxFIFO. Note: there is only one RxFIFO so
+ * we might as well use the addess associated with EP0.
+ */
+
+ regaddr = STM32_OTGFS_DFIFO_DEP(EP0);
+
+ /* Read 32-bits and write 4 x 8-bits at time (to avoid unaligned accesses) */
+
+ for (i = 0; i < len; i += 4)
+ {
+ union
+ {
+ uint32_t w;
+ uint8_t b[4];
+ } data;
+
+ /* Read 1 x 32-bits of EP0 packet data */
+
+ data.w = stm32_getreg(regaddr);
+
+ /* Write 4 x 8-bits of EP0 packet data */
+
+ *dest++ = data.b[0];
+ *dest++ = data.b[1];
+ *dest++ = data.b[2];
+ *dest++ = data.b[3];
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_rxfifo_discard
+ *
+ * Description:
+ * Discard packet data from the RxFIFO.
+ *
+ *******************************************************************************/
+
+static void stm32_rxfifo_discard(FAR struct stm32_ep_s *privep, int len)
+{
+ if (len > 0)
+ {
+ uint32_t regaddr;
+ int i;
+
+ /* Get the address of the RxFIFO Note: there is only one RxFIFO so
+ * we might as well use the addess associated with EP0.
+ */
+
+ regaddr = STM32_OTGFS_DFIFO_DEP(EP0);
+
+ /* Read 32-bits at time */
+
+ for (i = 0; i < len; i += 4)
+ {
+ volatile uint32_t data = stm32_getreg(regaddr);
+ (void)data;
+ }
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_epout_complete
+ *
+ * Description:
+ * This function is called when an OUT transfer complete interrupt is
+ * received. It completes the read request at the head of the endpoint's
+ * request queue.
+ *
+ *******************************************************************************/
+
+static void stm32_epout_complete(FAR struct stm32_usbdev_s *priv,
+ FAR struct stm32_ep_s *privep)
+{
+ struct stm32_req_s *privreq;
+
+ /* Since a transfer just completed, there must be a read request at the head of
+ * the endpoint request queue.
+ */
+
+ privreq = stm32_rqpeek(privep);
+ DEBUGASSERT(privreq);
+
+ if (!privreq)
+ {
+ /* An OUT transfer completed, but no packet to receive the data. This
+ * should not happen.
+ */
+
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTQEMPTY), privep->epphy);
+ privep->active = false;
+ return;
+ }
+
+ ullvdbg("EP%d: len=%d xfrd=%d\n",
+ privep->epphy, privreq->req.len, privreq->req.xfrd);
+
+ /* Return the completed read request to the class driver and mark the state
+ * IDLE.
+ */
+
+ usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
+ stm32_req_complete(privep, OK);
+ privep->active = false;
+
+ /* Now set up the next read request (if any) */
+
+ stm32_epout_request(priv, privep);
+}
+
+/*******************************************************************************
+ * Name: stm32_ep0out_receive
+ *
+ * Description:
+ * This function is called from the RXFLVL interrupt handler when new incoming
+ * data is available in the endpoint's RxFIFO. This function will simply
+ * copy the incoming data into pending request's data buffer.
+ *
+ *******************************************************************************/
+
+static inline void stm32_ep0out_receive(FAR struct stm32_ep_s *privep, int bcnt)
+{
+ FAR struct stm32_usbdev_s *priv;
+
+ /* Sanity Checking */
+
+ DEBUGASSERT(privep && privep->ep.priv);
+ priv = (FAR struct stm32_usbdev_s *)privep->ep.priv;
+ DEBUGASSERT(priv->ep0state == EP0STATE_SETUP_OUT);
+
+ ullvdbg("EP0: bcnt=%d\n", bcnt);
+ usbtrace(TRACE_READ(EP0), bcnt);
+
+ /* Verify that an OUT SETUP request as received before this data was
+ * received in the RxFIFO.
+ */
+
+ if (priv->ep0state == EP0STATE_SETUP_OUT)
+ {
+ /* Read the data into our special buffer for SETUP data */
+
+ int readlen = MIN(CONFIG_USBDEV_SETUP_MAXDATASIZE, bcnt);
+ stm32_rxfifo_read(privep, priv->ep0data, readlen);
+
+ /* Do we have to discard any excess bytes? */
+
+ stm32_rxfifo_discard(privep, bcnt - readlen);
+
+ /* Now we can process the setup command */
+
+ privep->active = false;
+ priv->ep0state = EP0STATE_SETUP_READY;
+ priv->ep0datlen = readlen;
+
+ stm32_ep0out_setup(priv);
+ }
+ else
+ {
+ /* This is an error. We don't have any idea what to do with the EP0
+ * data in this case. Just read and discard it so that the RxFIFO
+ * does not become constipated.
+ */
+
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_NOOUTSETUP), priv->ep0state);
+ stm32_rxfifo_discard(privep, bcnt);
+ privep->active = false;
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_epout_receive
+ *
+ * Description:
+ * This function is called from the RXFLVL interrupt handler when new incoming
+ * data is available in the endpoint's RxFIFO. This function will simply
+ * copy the incoming data into pending request's data buffer.
+ *
+ *******************************************************************************/
+
+static inline void stm32_epout_receive(FAR struct stm32_ep_s *privep, int bcnt)
+{
+ struct stm32_req_s *privreq;
+ uint8_t *dest;
+ int buflen;
+ int readlen;
+
+ /* Get a reference to the request at the head of the endpoint's request
+ * queue.
+ */
+
+ privreq = stm32_rqpeek(privep);
+ if (!privreq)
+ {
+ /* Incoming data is available in the RxFIFO, but there is no read setup
+ * to receive the receive the data. This should not happen for data
+ * endpoints; those endpoints should have been NAKing any OUT data tokens.
+ *
+ * We should get here normally on OUT data phase following an OUT
+ * SETUP command. EP0 data will still receive data in this case and it
+ * should not be NAKing.
+ */
+
+ if (privep->epphy == 0)
+ {
+ stm32_ep0out_receive(privep, bcnt);
+ }
+ else
+ {
+ /* Otherwise, the data is lost. This really should not happen if
+ * NAKing is working as expected.
+ */
+
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTQEMPTY), privep->epphy);
+
+ /* Discard the data in the RxFIFO */
+
+ stm32_rxfifo_discard(privep, bcnt);
+ }
+
+ privep->active = false;
+ return;
+ }
+
+ ullvdbg("EP%d: len=%d xfrd=%d\n", privep->epphy, privreq->req.len, privreq->req.xfrd);
+ usbtrace(TRACE_READ(privep->epphy), bcnt);
+
+ /* Get the number of bytes to transfer from the RxFIFO */
+
+ buflen = privreq->req.len - privreq->req.xfrd;
+ DEBUGASSERT(buflen > 0 && buflen >= bcnt);
+ readlen = MIN(buflen, bcnt);
+
+ /* Get the destination of the data transfer */
+
+ dest = privreq->req.buf + privreq->req.xfrd;
+
+ /* Transfer the data from the RxFIFO to the request's data buffer */
+
+ stm32_rxfifo_read(privep, dest, readlen);
+
+ /* If there were more bytes in the RxFIFO than could be held in the read
+ * request, then we will have to discard those.
+ */
+
+ stm32_rxfifo_discard(privep, bcnt - readlen);
+
+ /* Update the number of bytes transferred */
+
+ privreq->req.xfrd += readlen;
+}
+
+/*******************************************************************************
+ * Name: stm32_epout_request
+ *
+ * Description:
+ * This function is called when either (1) new read request is received, or
+ * (2) a pending receive request completes. If there is no read in pending,
+ * then this function will initiate the next OUT (read) operation.
+ *
+ *******************************************************************************/
+
+static void stm32_epout_request(FAR struct stm32_usbdev_s *priv,
+ FAR struct stm32_ep_s *privep)
+{
+ struct stm32_req_s *privreq;
+ uint32_t regaddr;
+ uint32_t regval;
+ uint32_t xfrsize;
+ uint32_t pktcnt;
+
+ /* Make sure that there is not already a pending request request. If there is,
+ * just return, leaving the newly received request in the request queue.
+ */
+
+ if (!privep->active)
+ {
+ /* Loop until a valid request is found (or the request queue is empty).
+ * The loop is only need to look at the request queue again is an invalid
+ * read request is encountered.
+ */
+
+ for (;;)
+ {
+ /* Get a reference to the request at the head of the endpoint's request queue */
+
+ privreq = stm32_rqpeek(privep);
+ if (!privreq)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTQEMPTY), privep->epphy);
+
+ /* There are no read requests to be setup. Configure the hardware to
+ * NAK any incoming packets. (This should already be the case. I
+ * think that the hardware will automatically NAK after a transfer is
+ * completed until SNAK is cleared).
+ */
+
+ regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ regval |= OTGFS_DOEPCTL_SNAK;
+ stm32_putreg(regval, regaddr);
+
+ /* This endpoint is no longer actively transferring */
+
+ privep->active = false;
+ return;
+ }
+
+ ullvdbg("EP%d: len=%d\n", privep->epphy, privreq->req.len);
+
+ /* Ignore any attempt to receive a zero length packet (this really
+ * should not happen.
+ */
+
+ if (privreq->req.len <= 0)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTNULLPACKET), 0);
+ stm32_req_complete(privep, OK);
+ }
+
+ /* Otherwise, we have a usable read request... break out of the loop */
+
+ else
+ {
+ break;
+ }
+ }
+
+ /* Setup the pending read into the request buffer. First calculate:
+ *
+ * pktcnt = the number of packets (of maxpacket bytes) required to
+ * perform the transfer.
+ * xfrsize = The total number of bytes required (in units of
+ * maxpacket bytes).
+ */
+
+ pktcnt = (privreq->req.len + (privep->ep.maxpacket - 1)) / privep->ep.maxpacket;
+ xfrsize = pktcnt * privep->ep.maxpacket;
+
+ /* Then setup the hardware to perform this transfer */
+
+ regaddr = STM32_OTGFS_DOEPTSIZ(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ regval &= ~(OTGFS_DOEPTSIZ_XFRSIZ_MASK | OTGFS_DOEPTSIZ_PKTCNT_MASK);
+ regval |= (xfrsize << OTGFS_DOEPTSIZ_XFRSIZ_SHIFT);
+ regval |= (pktcnt << OTGFS_DOEPTSIZ_PKTCNT_SHIFT);
+ stm32_putreg(regval, regaddr);
+
+ /* Then enable the transfer */
+
+ regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+
+ /* When an isochronous transfer is enabled the Even/Odd frame bit must
+ * also be set appropriately.
+ */
+
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+ if (privep->eptype == USB_EP_ATTR_XFER_ISOC)
+ {
+ if (privep->odd)
+ {
+ regval |= OTGFS_DOEPCTL_SODDFRM;
+ }
+ else
+ {
+ regval |= OTGFS_DOEPCTL_SEVNFRM;
+ }
+ }
+#endif
+
+ /* Clearing NAKing and enable the transfer. */
+
+ regval |= (OTGFS_DOEPCTL_CNAK | OTGFS_DOEPCTL_EPENA);
+ stm32_putreg(regval, regaddr);
+
+ /* A transfer is now active on this endpoint */
+
+ privep->active = true;
+
+ /* EP0 is a special case. We need to know when to switch back to
+ * normal SETUP processing.
+ */
+
+ if (privep->epphy == EP0)
+ {
+ priv->ep0state = EP0STATE_DATA_OUT;
+ }
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_flush
+ *
+ * Description:
+ * Flush any primed descriptors from this ep
+ *
+ *******************************************************************************/
+
+static void stm32_ep_flush(struct stm32_ep_s *privep)
+{
+ if (privep->isin)
+ {
+ stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_D(privep->epphy));
+ }
+ else
+ {
+ stm32_rxfifo_flush();
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_req_complete
+ *
+ * Description:
+ * Handle termination of the request at the head of the endpoint request queue.
+ *
+ *******************************************************************************/
+
+static void stm32_req_complete(struct stm32_ep_s *privep, int16_t result)
+{
+ FAR struct stm32_req_s *privreq;
+
+ /* Remove the request at the head of the request list */
+
+ privreq = stm32_req_remfirst(privep);
+ DEBUGASSERT(privreq != NULL);
+
+ /* If endpoint 0, temporarily reflect the state of protocol stalled
+ * in the callback.
+ */
+
+ bool stalled = privep->stalled;
+ if (privep->epphy == EP0)
+ {
+ privep->stalled = privep->dev->stalled;
+ }
+
+ /* Save the result in the request structure */
+
+ privreq->req.result = result;
+
+ /* Callback to the request completion handler */
+
+ privreq->req.callback(&privep->ep, &privreq->req);
+
+ /* Restore the stalled indication */
+
+ privep->stalled = stalled;
+}
+
+/*******************************************************************************
+ * Name: stm32_req_cancel
+ *
+ * Description:
+ * Cancel all pending requests for an endpoint
+ *
+ *******************************************************************************/
+
+static void stm32_req_cancel(struct stm32_ep_s *privep, int16_t status)
+{
+ if (!stm32_rqempty(privep))
+ {
+ stm32_ep_flush(privep);
+ }
+
+ while (!stm32_rqempty(privep))
+ {
+ usbtrace(TRACE_COMPLETE(privep->epphy),
+ (stm32_rqpeek(privep))->req.xfrd);
+ stm32_req_complete(privep, status);
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_findbyaddr
+ *
+ * Description:
+ * Find the physical endpoint structure corresponding to a logic endpoint
+ * address
+ *
+ *******************************************************************************/
+
+static struct stm32_ep_s *stm32_ep_findbyaddr(struct stm32_usbdev_s *priv,
+ uint16_t eplog)
+{
+ struct stm32_ep_s *privep;
+ uint8_t epphy = USB_EPNO(eplog);
+
+ if (epphy >= STM32_NENDPOINTS)
+ {
+ return NULL;
+ }
+
+ /* Is this an IN or an OUT endpoint? */
+
+ if (USB_ISEPIN(eplog))
+ {
+ privep = &priv->epin[epphy];
+ }
+ else
+ {
+ privep = &priv->epout[epphy];
+ }
+
+ /* Verify that the endpoint has been configured */
+
+ if (!privep->configured)
+ {
+ return NULL;
+ }
+
+ /* Return endpoint reference */
+
+ DEBUGASSERT(privep->epphy == epphy);
+ return privep;
+}
+
+/*******************************************************************************
+ * Name: stm32_req_dispatch
+ *
+ * Description:
+ * Provide unhandled setup actions to the class driver. This is logically part
+ * of the USB interrupt handler.
+ *
+ *******************************************************************************/
+
+static int stm32_req_dispatch(struct stm32_usbdev_s *priv,
+ const struct usb_ctrlreq_s *ctrl)
+{
+ int ret = -EIO;
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DISPATCH), 0);
+ if (priv->driver)
+ {
+ /* Forward to the control request to the class driver implementation */
+
+ ret = CLASS_SETUP(priv->driver, &priv->usbdev, ctrl,
+ priv->ep0data, priv->ep0datlen);
+ }
+
+ if (ret < 0)
+ {
+ /* Stall on failure */
+
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DISPATCHSTALL), 0);
+ priv->stalled = true;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_usbreset
+ *
+ * Description:
+ * Reset Usb engine
+ *
+ *******************************************************************************/
+
+static void stm32_usbreset(struct stm32_usbdev_s *priv)
+{
+ FAR struct stm32_ep_s *privep;
+ uint32_t regval;
+ int i;
+
+ /* Clear the Remote Wake-up Signaling */
+
+ regval = stm32_getreg(STM32_OTGFS_DCTL);
+ regval &= ~OTGFS_DCTL_RWUSIG;
+ stm32_putreg(regval, STM32_OTGFS_DCTL);
+
+ /* Flush the EP0 Tx FIFO */
+
+ stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_D(EP0));
+
+ /* Tell the class driver that we are disconnected. The class
+ * driver should then accept any new configurations.
+ */
+
+ if (priv->driver)
+ {
+ CLASS_DISCONNECT(priv->driver, &priv->usbdev);
+ }
+ priv->epavail = STM32_EP_AVAILABLE;
+
+ /* Disable all end point interrupts */
+
+ for (i = 0; i < STM32_NENDPOINTS ; i++)
+ {
+ /* Disable endpoint interrupts */
+
+ stm32_putreg(0xff, STM32_OTGFS_DIEPINT(i));
+ stm32_putreg(0xff, STM32_OTGFS_DOEPINT(i));
+
+ /* Return write requests to the class implementation */
+
+ privep = &priv->epin[i];
+ stm32_req_cancel(privep, -ESHUTDOWN);
+
+ /* Reset IN endpoint status */
+
+ privep->stalled = false;
+
+ /* Return read requests to the class implementation */
+
+ privep = &priv->epout[i];
+ stm32_req_cancel(privep, -ESHUTDOWN);
+
+ /* Reset endpoint status */
+
+ privep->stalled = false;
+ }
+
+ stm32_putreg(0xffffffff, STM32_OTGFS_DAINT);
+
+ /* Mask all device endpoint interrupts except EP0 */
+
+ regval = (OTGFS_DAINT_IEP(EP0) | OTGFS_DAINT_OEP(EP0));
+ stm32_putreg(regval, STM32_OTGFS_DAINTMSK);
+
+ /* Unmask OUT interrupts */
+
+ regval = (OTGFS_DOEPMSK_XFRCM | OTGFS_DOEPMSK_STUPM | OTGFS_DOEPMSK_EPDM);
+ stm32_putreg(regval, STM32_OTGFS_DOEPMSK);
+
+ /* Unmask IN interrupts */
+
+ regval = (OTGFS_DIEPMSK_XFRCM | OTGFS_DIEPMSK_EPDM | OTGFS_DIEPMSK_TOM);
+ stm32_putreg(regval, STM32_OTGFS_DIEPMSK);
+
+ /* Reset device address to 0 */
+
+ stm32_setaddress(priv, 0);
+ priv->devstate = DEVSTATE_DEFAULT;
+ priv->usbdev.speed = USB_SPEED_FULL;
+
+ /* Re-configure EP0 */
+
+ stm32_ep0_configure(priv);
+
+ /* Setup EP0 to receive SETUP packets */
+
+ stm32_ep0out_ctrlsetup(priv);
+}
+
+/*******************************************************************************
+ * Name: stm32_ep0out_testmode
+ *
+ * Description:
+ * Select test mode
+ *
+ *******************************************************************************/
+
+static inline void stm32_ep0out_testmode(FAR struct stm32_usbdev_s *priv,
+ uint16_t index)
+{
+ uint32_t regval;
+ uint8_t testmode;
+
+ regval = stm32_getreg(STM32_OTGFS_DCTL);
+
+ testmode = index >> 8;
+ switch (testmode)
+ {
+ case 1:
+ priv->testmode = OTGFS_TESTMODE_J;
+ break;
+
+ case 2:
+ priv->testmode = OTGFS_TESTMODE_K;
+ break;
+
+ case 3:
+ priv->testmode = OTGFS_TESTMODE_SE0_NAK;
+ break;
+
+ case 4:
+ priv->testmode = OTGFS_TESTMODE_PACKET;
+ break;
+
+ case 5:
+ priv->testmode = OTGFS_TESTMODE_FORCE;
+ break;
+
+ default:
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADTESTMODE), testmode);
+ priv->dotest = false;
+ priv->testmode = OTGFS_TESTMODE_DISABLED;
+ priv->stalled = true;
+ }
+
+ priv->dotest = true;
+ stm32_ep0in_transmitzlp(priv);
+}
+
+/*******************************************************************************
+ * Name: stm32_ep0out_stdrequest
+ *
+ * Description:
+ * Handle a stanard request on EP0. Pick off the things of interest to the
+ * USB device controller driver; pass what is left to the class driver.
+ *
+ *******************************************************************************/
+
+static inline void stm32_ep0out_stdrequest(struct stm32_usbdev_s *priv,
+ FAR struct stm32_ctrlreq_s *ctrlreq)
+{
+ FAR struct stm32_ep_s *privep;
+
+ /* Handle standard request */
+
+ switch (ctrlreq->req)
+ {
+ case USB_REQ_GETSTATUS:
+ {
+ /* type: device-to-host; recipient = device, interface, endpoint
+ * value: 0
+ * index: zero interface endpoint
+ * len: 2; data = status
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSTATUS), 0);
+ if (!priv->addressed ||
+ ctrlreq->len != 2 ||
+ USB_REQ_ISOUT(ctrlreq->type) ||
+ ctrlreq->value != 0)
+ {
+ priv->stalled = true;
+ }
+ else
+ {
+ switch (ctrlreq->type & USB_REQ_RECIPIENT_MASK)
+ {
+ case USB_REQ_RECIPIENT_ENDPOINT:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPGETSTATUS), 0);
+ privep = stm32_ep_findbyaddr(priv, ctrlreq->index);
+ if (!privep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPGETSTATUS), 0);
+ priv->stalled = true;
+ }
+ else
+ {
+ if (privep->stalled)
+ {
+ priv->ep0data[0] = (1 << USB_FEATURE_ENDPOINTHALT);
+ }
+ else
+ {
+ priv->ep0data[0] = 0; /* Not stalled */
+ }
+
+ priv->ep0data[1] = 0;
+ stm32_ep0in_setupresponse(priv, priv->ep0data, 2);
+ }
+ }
+ break;
+
+ case USB_REQ_RECIPIENT_DEVICE:
+ {
+ if (ctrlreq->index == 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DEVGETSTATUS), 0);
+
+ /* Features: Remote Wakeup and selfpowered */
+
+ priv->ep0data[0] = (priv->selfpowered << USB_FEATURE_SELFPOWERED);
+ priv->ep0data[0] |= (priv->wakeup << USB_FEATURE_REMOTEWAKEUP);
+ priv->ep0data[1] = 0;
+
+ stm32_ep0in_setupresponse(priv, priv->ep0data, 2);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADDEVGETSTATUS), 0);
+ priv->stalled = true;
+ }
+ }
+ break;
+
+ case USB_REQ_RECIPIENT_INTERFACE:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_IFGETSTATUS), 0);
+ priv->ep0data[0] = 0;
+ priv->ep0data[1] = 0;
+
+ stm32_ep0in_setupresponse(priv, priv->ep0data, 2);
+ }
+ break;
+
+ default:
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSTATUS), 0);
+ priv->stalled = true;
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ case USB_REQ_CLEARFEATURE:
+ {
+ /* type: host-to-device; recipient = device, interface or endpoint
+ * value: feature selector
+ * index: zero interface endpoint;
+ * len: zero, data = none
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_CLEARFEATURE), 0);
+ if (priv->addressed != 0 && ctrlreq->len == 0)
+ {
+ uint8_t recipient = ctrlreq->type & USB_REQ_RECIPIENT_MASK;
+ if (recipient == USB_REQ_RECIPIENT_ENDPOINT &&
+ ctrlreq->value == USB_FEATURE_ENDPOINTHALT &&
+ (privep = stm32_ep_findbyaddr(priv, ctrlreq->index)) != NULL)
+ {
+ stm32_ep_clrstall(privep);
+ stm32_ep0in_transmitzlp(priv);
+ }
+ else if (recipient == USB_REQ_RECIPIENT_DEVICE &&
+ ctrlreq->value == USB_FEATURE_REMOTEWAKEUP)
+ {
+ priv->wakeup = 0;
+ stm32_ep0in_transmitzlp(priv);
+ }
+ else
+ {
+ /* Actually, I think we could just stall here. */
+
+ (void)stm32_req_dispatch(priv, &priv->ctrlreq);
+ }
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADCLEARFEATURE), 0);
+ priv->stalled = true;
+ }
+ }
+ break;
+
+ case USB_REQ_SETFEATURE:
+ {
+ /* type: host-to-device; recipient = device, interface, endpoint
+ * value: feature selector
+ * index: zero interface endpoint;
+ * len: 0; data = none
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETFEATURE), 0);
+ if (priv->addressed != 0 && ctrlreq->len == 0)
+ {
+ uint8_t recipient = ctrlreq->type & USB_REQ_RECIPIENT_MASK;
+ if (recipient == USB_REQ_RECIPIENT_ENDPOINT &&
+ ctrlreq->value == USB_FEATURE_ENDPOINTHALT &&
+ (privep = stm32_ep_findbyaddr(priv, ctrlreq->index)) != NULL)
+ {
+ stm32_ep_setstall(privep);
+ stm32_ep0in_transmitzlp(priv);
+ }
+ else if (recipient == USB_REQ_RECIPIENT_DEVICE &&
+ ctrlreq->value == USB_FEATURE_REMOTEWAKEUP)
+ {
+ priv->wakeup = 1;
+ stm32_ep0in_transmitzlp(priv);
+ }
+ else if (recipient == USB_REQ_RECIPIENT_DEVICE &&
+ ctrlreq->value == USB_FEATURE_TESTMODE &&
+ ((ctrlreq->index & 0xff) == 0))
+ {
+ stm32_ep0out_testmode(priv, ctrlreq->index);
+ }
+ else if (priv->configured)
+ {
+ /* Actually, I think we could just stall here. */
+
+ (void)stm32_req_dispatch(priv, &priv->ctrlreq);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETFEATURE), 0);
+ priv->stalled = true;
+ }
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETFEATURE), 0);
+ priv->stalled = true;
+ }
+ }
+ break;
+
+ case USB_REQ_SETADDRESS:
+ {
+ /* type: host-to-device; recipient = device
+ * value: device address
+ * index: 0
+ * len: 0; data = none
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETADDRESS), ctrlreq->value);
+ if ((ctrlreq->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
+ ctrlreq->index == 0 &&
+ ctrlreq->len == 0 &&
+ ctrlreq->value < 128 &&
+ priv->devstate != DEVSTATE_CONFIGURED)
+ {
+ /* Save the address. We cannot actually change to the next address until
+ * the completion of the status phase.
+ */
+
+ stm32_setaddress(priv, (uint16_t)priv->ctrlreq.value[0]);
+ stm32_ep0in_transmitzlp(priv);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETADDRESS), 0);
+ priv->stalled = true;
+ }
+ }
+ break;
+
+ case USB_REQ_GETDESCRIPTOR:
+ /* type: device-to-host; recipient = device
+ * value: descriptor type and index
+ * index: 0 or language ID;
+ * len: descriptor len; data = descriptor
+ */
+
+ case USB_REQ_SETDESCRIPTOR:
+ /* type: host-to-device; recipient = device
+ * value: descriptor type and index
+ * index: 0 or language ID;
+ * len: descriptor len; data = descriptor
+ */
+
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSETDESC), 0);
+ if ((ctrlreq->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE)
+ {
+ (void)stm32_req_dispatch(priv, &priv->ctrlreq);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSETDESC), 0);
+ priv->stalled = true;
+ }
+ }
+ break;
+
+ case USB_REQ_GETCONFIGURATION:
+ /* type: device-to-host; recipient = device
+ * value: 0;
+ * index: 0;
+ * len: 1; data = configuration value
+ */
+
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETCONFIG), 0);
+ if (priv->addressed &&
+ (ctrlreq->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
+ ctrlreq->value == 0 &&
+ ctrlreq->index == 0 &&
+ ctrlreq->len == 1)
+ {
+ (void)stm32_req_dispatch(priv, &priv->ctrlreq);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETCONFIG), 0);
+ priv->stalled = true;
+ }
+ }
+ break;
+
+ case USB_REQ_SETCONFIGURATION:
+ /* type: host-to-device; recipient = device
+ * value: configuration value
+ * index: 0;
+ * len: 0; data = none
+ */
+
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETCONFIG), 0);
+ if (priv->addressed &&
+ (ctrlreq->type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
+ ctrlreq->index == 0 &&
+ ctrlreq->len == 0)
+ {
+ /* Give the configuration to the class driver */
+
+ int ret = stm32_req_dispatch(priv, &priv->ctrlreq);
+
+ /* If the class driver accepted the configuration, then mark the
+ * device state as configured (or not, depending on the
+ * configuration).
+ */
+
+ if (ret == OK)
+ {
+ uint8_t cfg = (uint8_t)ctrlreq->value;
+ if (cfg != 0)
+ {
+ priv->devstate = DEVSTATE_CONFIGURED;
+ priv->configured = true;
+ }
+ else
+ {
+ priv->devstate = DEVSTATE_ADDRESSED;
+ priv->configured = false;
+ }
+ }
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETCONFIG), 0);
+ priv->stalled = true;
+ }
+ }
+ break;
+
+ case USB_REQ_GETINTERFACE:
+ /* type: device-to-host; recipient = interface
+ * value: 0
+ * index: interface;
+ * len: 1; data = alt interface
+ */
+
+ case USB_REQ_SETINTERFACE:
+ /* type: host-to-device; recipient = interface
+ * value: alternate setting
+ * index: interface;
+ * len: 0; data = none
+ */
+
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSETIF), 0);
+ (void)stm32_req_dispatch(priv, &priv->ctrlreq);
+ }
+ break;
+
+ case USB_REQ_SYNCHFRAME:
+ /* type: device-to-host; recipient = endpoint
+ * value: 0
+ * index: endpoint;
+ * len: 2; data = frame number
+ */
+
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SYNCHFRAME), 0);
+ }
+ break;
+
+ default:
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDCTRLREQ), 0);
+ priv->stalled = true;
+ }
+ break;
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_ep0out_setup
+ *
+ * Description:
+ * USB Ctrl EP Setup Event. This is logically part of the USB interrupt
+ * handler. This event occurs when a setup packet is receive on EP0 OUT.
+ *
+ *******************************************************************************/
+
+static inline void stm32_ep0out_setup(struct stm32_usbdev_s *priv)
+{
+ struct stm32_ctrlreq_s ctrlreq;
+
+ /* Verify that a SETUP was received */
+
+ if (priv->ep0state != EP0STATE_SETUP_READY)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0NOSETUP), priv->ep0state);
+ return;
+ }
+
+ /* Terminate any pending requests */
+
+ stm32_req_cancel(&priv->epout[EP0], -EPROTO);
+ stm32_req_cancel(&priv->epin[EP0], -EPROTO);
+
+ /* Assume NOT stalled */
+
+ priv->epout[EP0].stalled = false;
+ priv->epin[EP0].stalled = false;
+ priv->stalled = false;
+
+ /* Starting to process a control request - update state */
+
+ priv->ep0state = EP0STATE_SETUP_PROCESS;
+
+ /* And extract the little-endian 16-bit values to host order */
+
+ ctrlreq.type = priv->ctrlreq.type;
+ ctrlreq.req = priv->ctrlreq.req;
+ ctrlreq.value = GETUINT16(priv->ctrlreq.value);
+ ctrlreq.index = GETUINT16(priv->ctrlreq.index);
+ ctrlreq.len = GETUINT16(priv->ctrlreq.len);
+
+ ullvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n",
+ ctrlreq.type, ctrlreq.req, ctrlreq.value, ctrlreq.index, ctrlreq.len);
+
+ /* Check for a standard request */
+
+ if ((ctrlreq.type & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD)
+ {
+ /* Dispatch any non-standard requests */
+
+ (void)stm32_req_dispatch(priv, &priv->ctrlreq);
+ }
+ else
+ {
+ /* Handle standard requests. */
+
+ stm32_ep0out_stdrequest(priv, &ctrlreq);
+ }
+
+ /* Check if the setup processing resulted in a STALL */
+
+ if (priv->stalled)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->ep0state);
+ stm32_ep0_stall(priv);
+ }
+
+ /* Reset state/data associated with thie SETUP request */
+
+ priv->ep0datlen = 0;
+}
+
+/*******************************************************************************
+ * Name: stm32_epout
+ *
+ * Description:
+ * This is part of the OUT endpoint interrupt processing. This function
+ * handles the OUT event for a single endpoint.
+ *
+ *******************************************************************************/
+
+static inline void stm32_epout(FAR struct stm32_usbdev_s *priv, uint8_t epno)
+{
+ FAR struct stm32_ep_s *privep;
+
+ /* Endpoint 0 is a special case. */
+
+ if (epno == 0)
+ {
+ privep = &priv->epout[EP0];
+
+ /* In the EP0STATE_DATA_OUT state, we are receiving data into the
+ * request buffer. In that case, we must continue the request
+ * processing.
+ */
+
+ if (priv->ep0state == EP0STATE_DATA_OUT)
+ {
+ /* Continue processing data from the EP0 OUT request queue */
+
+ stm32_epout_complete(priv, privep);
+ }
+
+ /* If we are not actively processing an OUT request, then we
+ * need to setup to receive the next control request.
+ */
+
+ if (!privep->active)
+ {
+ stm32_ep0out_ctrlsetup(priv);
+ priv->ep0state = EP0STATE_IDLE;
+ }
+ }
+
+ /* For other endpoints, the only possibility is that we are continuing
+ * or finishing an OUT request.
+ */
+
+ else if (priv->devstate == DEVSTATE_CONFIGURED)
+ {
+ stm32_epout_complete(priv, &priv->epout[epno]);
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_epout_interrupt
+ *
+ * Description:
+ * USB OUT endpoint interrupt handler. The core generates this interrupt when
+ * there is an interrupt is pending on one of the OUT endpoints of the core.
+ * The driver must read the OTGFS DAINT register to determine the exact number
+ * of the OUT endpoint on which the interrupt occurred, and then read the
+ * corresponding OTGFS DOEPINTx register to determine the exact cause of the
+ * interrupt.
+ *
+ *******************************************************************************/
+
+static inline void stm32_epout_interrupt(FAR struct stm32_usbdev_s *priv)
+{
+ uint32_t daint;
+ uint32_t regval;
+ uint32_t doepint;
+ int epno;
+
+ /* Get the pending, enabled interrupts for the OUT endpoint from the endpoint
+ * interrupt status register.
+ */
+
+ regval = stm32_getreg(STM32_OTGFS_DAINT);
+ regval &= stm32_getreg(STM32_OTGFS_DAINTMSK);
+ daint = (regval & OTGFS_DAINT_OEP_MASK) >> OTGFS_DAINT_OEP_SHIFT;
+
+ /* Process each pending IN endpoint interrupt */
+
+ epno = 0;
+ while (daint)
+ {
+ /* Is an OUT interrupt pending for this endpoint? */
+
+ if ((daint & 1) != 0)
+ {
+ /* Yes.. get the OUT endpoint interrupt status */
+
+ doepint = stm32_getreg(STM32_OTGFS_DOEPINT(epno));
+ doepint &= stm32_getreg(STM32_OTGFS_DOEPMSK);
+
+ /* Transfer completed interrupt. This interrupt is trigged when
+ * stm32_rxinterrupt() removes the last packet data from the RxFIFO.
+ * In this case, core internally sets the NAK bit for this endpoint to
+ * prevent it from receiving any more packets.
+ */
+
+ if ((doepint & OTGFS_DOEPINT_XFRC) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUT_XFRC), (uint16_t)doepint);
+
+ /* Clear the bit in DOEPINTn for this interrupt */
+
+ stm32_putreg(OTGFS_DOEPINT_XFRC, STM32_OTGFS_DOEPINT(epno));
+
+ /* Handle the RX transfer data ready event */
+
+ stm32_epout(priv, epno);
+ }
+
+ /* Endpoint disabled interrupt (ignored because this interrrupt is
+ * used in polled mode by the endpoint disable logic).
+ */
+#if 1
+ /* REVISIT: */
+ if ((doepint & OTGFS_DOEPINT_EPDISD) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUT_EPDISD), (uint16_t)doepint);
+
+ /* Clear the bit in DOEPINTn for this interrupt */
+
+ stm32_putreg(OTGFS_DOEPINT_EPDISD, STM32_OTGFS_DOEPINT(epno));
+ }
+#endif
+ /* Setup Phase Done (control EPs) */
+
+ if ((doepint & OTGFS_DOEPINT_SETUP) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUT_SETUP), priv->ep0state);
+
+ /* Handle the receipt of the IN SETUP packets now (OUT setup
+ * packet processing may be delayed until the accompanying
+ * OUT DATA is received)
+ */
+
+ if (priv->ep0state == EP0STATE_SETUP_READY)
+ {
+ stm32_ep0out_setup(priv);
+ }
+ stm32_putreg(OTGFS_DOEPINT_SETUP, STM32_OTGFS_DOEPINT(epno));
+ }
+ }
+
+ epno++;
+ daint >>= 1;
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_epin_runtestmode
+ *
+ * Description:
+ * Execute the test mode setup by the SET FEATURE request
+ *
+ *******************************************************************************/
+
+static inline void stm32_epin_runtestmode(FAR struct stm32_usbdev_s *priv)
+{
+ uint32_t regval = stm32_getreg(STM32_OTGFS_DCTL);
+ regval &= OTGFS_DCTL_TCTL_MASK;
+ regval |= (uint32_t)priv->testmode << OTGFS_DCTL_TCTL_SHIFT;
+ stm32_putreg(regval , STM32_OTGFS_DCTL);
+
+ priv->dotest = 0;
+ priv->testmode = OTGFS_TESTMODE_DISABLED;
+}
+
+/*******************************************************************************
+ * Name: stm32_epin
+ *
+ * Description:
+ * This is part of the IN endpoint interrupt processing. This function
+ * handles the IN event for a single endpoint.
+ *
+ *******************************************************************************/
+
+static inline void stm32_epin(FAR struct stm32_usbdev_s *priv, uint8_t epno)
+{
+ FAR struct stm32_ep_s *privep = &priv->epin[epno];
+
+ /* Endpoint 0 is a special case. */
+
+ if (epno == 0)
+ {
+ /* In the EP0STATE_DATA_IN state, we are sending data from request
+ * buffer. In that case, we must continue the request processing.
+ */
+
+ if (priv->ep0state == EP0STATE_DATA_IN)
+ {
+ /* Continue processing data from the EP0 OUT request queue */
+
+ stm32_epin_request(priv, privep);
+ }
+
+ /* If we are not actively processing an OUT request, then we
+ * need to setup to receive the next control request.
+ */
+
+ if (!privep->active)
+ {
+ stm32_ep0out_ctrlsetup(priv);
+ priv->ep0state = EP0STATE_IDLE;
+ }
+
+ /* Test mode is another special case */
+
+ if (priv->dotest)
+ {
+ stm32_epin_runtestmode(priv);
+ }
+ }
+
+ /* For other endpoints, the only possibility is that we are continuing
+ * or finishing an IN request.
+ */
+
+ else if (priv->devstate == DEVSTATE_CONFIGURED)
+ {
+ /* Continue processing data from the endpoint write request queue */
+
+ stm32_epin_request(priv, privep);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_epin_txfifoempty
+ *
+ * Description:
+ * TxFIFO empty interrupt handling
+ *
+ ****************************************************************************/
+
+static inline void stm32_epin_txfifoempty(FAR struct stm32_usbdev_s *priv, int epno)
+{
+ FAR struct stm32_ep_s *privep = &priv->epin[epno];
+
+ /* Continue processing the write request queue. This may mean sending
+ * more dat from the exisiting request or terminating the current requests
+ * and (perhaps) starting the IN transfer from the next write request.
+ */
+
+ stm32_epin_request(priv, privep);
+}
+
+/*******************************************************************************
+ * Name: stm32_epin_interrupt
+ *
+ * Description:
+ * USB IN endpoint interrupt handler. The core generates this interrupt when
+ * an interrupt is pending on one of the IN endpoints of the core. The driver
+ * must read the OTGFS DAINT register to determine the exact number of the IN
+ * endpoint on which the interrupt occurred, and then read the corresponding
+ * OTGFS DIEPINTx register to determine the exact cause of the interrupt.
+ *
+ *******************************************************************************/
+
+static inline void stm32_epin_interrupt(FAR struct stm32_usbdev_s *priv)
+{
+ uint32_t diepint;
+ uint32_t daint;
+ uint32_t mask;
+ uint32_t empty;
+ int epno;
+
+ /* Get the pending, enabled interrupts for the IN endpoint from the endpoint
+ * interrupt status register.
+ */
+
+ daint = stm32_getreg(STM32_OTGFS_DAINT);
+ daint &= stm32_getreg(STM32_OTGFS_DAINTMSK);
+ daint &= OTGFS_DAINT_IEP_MASK;
+
+ /* Process each pending IN endpoint interrupt */
+
+ epno = 0;
+ while (daint)
+ {
+ /* Is an IN interrupt pending for this endpoint? */
+
+ if ((daint & 1) != 0)
+ {
+ /* Get IN interrupt mask register. Bits 0-6 correspond to enabled
+ * interrupts as will be found in the DIEPINT interrupt status
+ * register.
+ */
+
+ mask = stm32_getreg(STM32_OTGFS_DIEPMSK);
+
+ /* Check for FIFO not empty. Bits n corresponds to endpoint n.
+ * That condition corresponds to bit 7 of the DIEPINT interrupt
+ * status register.
+ */
+
+ empty = stm32_getreg(STM32_OTGFS_DIEPEMPMSK);
+ if ((empty & OTGFS_DIEPEMPMSK(epno)) != 0)
+ {
+ mask |= OTGFS_DIEPINT_TXFE;
+ }
+
+ /* Now, read the interrupt status and mask out all disabled
+ * interrupts.
+ */
+
+ diepint = stm32_getreg(STM32_OTGFS_DIEPINT(epno)) & mask;
+
+ /* Decode and process the enabled, pending interrupts */
+ /* Transfer completed interrupt */
+
+ if ((diepint & OTGFS_DIEPINT_XFRC) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_XFRC), (uint16_t)diepint);
+
+ /* It is possible that logic may be waiting for a the TxFIFO to become
+ * empty. We disable the TxFIFO empty interrupt here; it will be
+ * re-enabled if there is still insufficient space in the TxFIFO.
+ */
+
+ empty &= ~OTGFS_DIEPEMPMSK(epno);
+ stm32_putreg(empty, STM32_OTGFS_DIEPEMPMSK);
+ stm32_putreg(OTGFS_DIEPINT_XFRC, STM32_OTGFS_DIEPINT(epno));
+
+ /* IN transfer complete */
+
+ stm32_epin(priv, epno);
+ }
+
+ /* Timeout condition */
+
+ if ((diepint & OTGFS_DIEPINT_TOC) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_TOC), (uint16_t)diepint);
+ stm32_putreg(OTGFS_DIEPINT_TOC, STM32_OTGFS_DIEPINT(epno));
+ }
+
+ /* IN token received when TxFIFO is empty. Applies to non-periodic IN
+ * endpoints only. This interrupt indicates that an IN token was received
+ * when the associated TxFIFO (periodic/non-periodic) was empty. This
+ * interrupt is asserted on the endpoint for which the IN token was
+ * received.
+ */
+
+ if ((diepint & OTGFS_DIEPINT_ITTXFE) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_ITTXFE), (uint16_t)diepint);
+ stm32_epin_request(priv, &priv->epin[epno]);
+ stm32_putreg(OTGFS_DIEPINT_ITTXFE, STM32_OTGFS_DIEPINT(epno));
+ }
+
+ /* IN endpoint NAK effective (ignored as this used only in polled
+ * mode)
+ */
+#if 0
+ if ((diepint & OTGFS_DIEPINT_INEPNE) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_INEPNE), (uint16_t)diepint);
+ stm32_putreg(OTGFS_DIEPINT_INEPNE, STM32_OTGFS_DIEPINT(epno));
+ }
+#endif
+ /* Endpoint disabled interrupt (ignored as this used only in polled
+ * mode)
+ */
+#if 0
+ if ((diepint & OTGFS_DIEPINT_EPDISD) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_EPDISD), (uint16_t)diepint);
+ stm32_putreg(OTGFS_DIEPINT_EPDISD, STM32_OTGFS_DIEPINT(epno));
+ }
+#endif
+ /* Transmit FIFO empty */
+
+ if ((diepint & OTGFS_DIEPINT_TXFE) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_TXFE), (uint16_t)diepint);
+
+ /* If we were waiting for TxFIFO to become empty, the we might have both
+ * XFRC and TXFE interrups pending. Since we do the same thing for both
+ * cases, ignore the TXFE if we have already processed the XFRC.
+ */
+
+ if ((diepint & OTGFS_DIEPINT_XFRC) == 0)
+ {
+ /* Mask further FIFO empty interrupts. This will be re-enabled
+ * whenever we need to wait for a FIFO event.
+ */
+
+ empty &= ~OTGFS_DIEPEMPMSK(epno);
+ stm32_putreg(empty, STM32_OTGFS_DIEPEMPMSK);
+
+ /* Handle TxFIFO empty */
+
+ stm32_epin_txfifoempty(priv, epno);
+ }
+
+ /* Clear the pending TxFIFO empty interrupt */
+
+ stm32_putreg(OTGFS_DIEPINT_TXFE, STM32_OTGFS_DIEPINT(epno));
+ }
+ }
+
+ epno++;
+ daint >>= 1;
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_resumeinterrupt
+ *
+ * Description:
+ * Resume/remote wakeup detected interrupt
+ *
+ *******************************************************************************/
+
+static inline void stm32_resumeinterrupt(FAR struct stm32_usbdev_s *priv)
+{
+ uint32_t regval;
+
+ /* Restart the PHY clock and un-gate USB core clock (HCLK) */
+
+#ifdef CONFIG_USBDEV_LOWPOWER
+ regval = stm32_getreg(STM32_OTGFS_PCGCCTL);
+ regval &= ~(OTGFS_PCGCCTL_STPPCLK | OTGFS_PCGCCTL_GATEHCLK);
+ stm32_putreg(regval, STM32_OTGFS_PCGCCTL);
+#endif
+
+ /* Clear remote wake-up signaling */
+
+ regval = stm32_getreg(STM32_OTGFS_DCTL);
+ regval &= ~OTGFS_DCTL_RWUSIG;
+ stm32_putreg(regval, STM32_OTGFS_DCTL);
+
+ /* Restore full power -- whatever that means for this particular board */
+
+ stm32_usbsuspend((struct usbdev_s *)priv, true);
+}
+
+/*******************************************************************************
+ * Name: stm32_suspendinterrupt
+ *
+ * Description:
+ * USB suspend interrupt
+ *
+ *******************************************************************************/
+
+static inline void stm32_suspendinterrupt(FAR struct stm32_usbdev_s *priv)
+{
+#ifdef CONFIG_USBDEV_LOWPOWER
+ uint32_t regval;
+
+ /* OTGFS_DSTS_SUSPSTS is set as long as the suspend condition is detected
+ * on USB. Check if we are still have the suspend condition, that we are
+ * connected to the host, and that we have been configured.
+ */
+
+ regval = stm32_getreg(STM32_OTGFS_DSTS);
+
+ if ((regval & OTGFS_DSTS_SUSPSTS) != 0 &&
+ priv->connected &&
+ devstate == DEVSTATE_CONFIGURED)
+ {
+ /* Switch off OTG FS clocking. Setting OTGFS_PCGCCTL_STPPCLK stops the
+ * PHY clock.
+ */
+
+ regval = stm32_getreg(STM32_OTGFS_PCGCCTL);
+ regval |= OTGFS_PCGCCTL_STPPCLK;
+ stm32_putreg(regval, STM32_OTGFS_PCGCCTL);
+
+ /* Setting OTGFS_PCGCCTL_GATEHCLK gate HCLK to modules other than
+ * the AHB Slave and Master and wakeup logic.
+ */
+
+ regval |= OTGFS_PCGCCTL_GATEHCLK;
+ stm32_putreg(regval, STM32_OTGFS_PCGCCTL);
+ }
+#endif
+
+ /* Let the board-specific logic know that we have entered the suspend
+ * state
+ */
+
+ stm32_usbsuspend((FAR struct usbdev_s *)priv, false);
+}
+
+/*******************************************************************************
+ * Name: stm32_rxinterrupt
+ *
+ * Description:
+ * RxFIFO non-empty interrupt. This interrupt indicates that there is at
+ * least one packet pending to be read from the RxFIFO.
+ *
+ *******************************************************************************/
+
+static inline void stm32_rxinterrupt(FAR struct stm32_usbdev_s *priv)
+{
+ FAR struct stm32_ep_s *privep;
+ uint32_t regval;
+ int bcnt;
+ int epphy;
+
+ /* Disable the Rx status queue level interrupt */
+
+ regval = stm32_getreg(STM32_OTGFS_GINTMSK);
+ regval &= ~OTGFS_GINT_RXFLVL;
+ stm32_putreg(regval, STM32_OTGFS_GINTMSK);
+
+ /* Get the status from the top of the FIFO */
+
+ regval = stm32_getreg(STM32_OTGFS_GRXSTSP);
+
+ /* Decode status fields */
+
+ epphy = (regval & OTGFS_GRXSTSD_EPNUM_MASK) >> OTGFS_GRXSTSD_EPNUM_SHIFT;
+ privep = &priv->epout[epphy];
+
+ /* Handle the RX event according to the packet status field */
+
+ switch (regval & OTGFS_GRXSTSD_PKTSTS_MASK)
+ {
+ /* Global OUT NAK. This indicate that the global OUT NAK bit has taken
+ * effect.
+ *
+ * PKTSTS = Global OUT NAK, BCNT = 0, EPNUM = Don't Care, DPID = Don't
+ * Care.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_OUTNAK:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTNAK), 0);
+ }
+ break;
+
+ /* OUT data packet received.
+ *
+ * PKTSTS = DataOUT, BCNT = size of the received data OUT packet,
+ * EPNUM = EPNUM on which the packet was received, DPID = Actual Data PID.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_OUTRECVD:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTRECVD), epphy);
+ bcnt = (regval & OTGFS_GRXSTSD_BCNT_MASK) >> OTGFS_GRXSTSD_BCNT_SHIFT;
+ if (bcnt > 0)
+ {
+ stm32_epout_receive(privep, bcnt);
+ }
+ }
+ break;
+
+ /* OUT transfer completed. This indicates that an OUT data transfer for
+ * the specified OUT endpoint has completed. After this entry is popped
+ * from the receive FIFO, the core asserts a Transfer Completed interrupt
+ * on the specified OUT endpoint.
+ *
+ * PKTSTS = Data OUT Transfer Done, BCNT = 0, EPNUM = OUT EP Num on
+ * which the data transfer is complete, DPID = Don't Care.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_OUTDONE:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTDONE), epphy);
+ }
+ break;
+
+ /* SETUP transaction completed. This indicates that the Setup stage for
+ * the specified endpoint has completed and the Data stage has started.
+ * After this entry is popped from the receive FIFO, the core asserts a
+ * Setup interrupt on the specified control OUT endpoint (triggers an
+ * interrupt).
+ *
+ * PKTSTS = Setup Stage Done, BCNT = 0, EPNUM = Control EP Num,
+ * DPID = Don't Care.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_SETUPDONE:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPDONE), epphy);
+ }
+ break;
+
+ /* SETUP data packet received. This indicates that a SETUP packet for the
+ * specified endpoint is now available for reading from the receive FIFO.
+ *
+ * PKTSTS = SETUP, BCNT = 8, EPNUM = Control EP Num, DPID = D0.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_SETUPRECVD:
+ {
+ uint16_t datlen;
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPRECVD), epphy);
+
+ /* Read EP0 setup data. NOTE: If multiple SETUP packets are received,
+ * the last one overwrites the previous setup packets and only that
+ * last SETUP packet will be processed.
+ */
+
+ stm32_rxfifo_read(&priv->epout[EP0], (FAR uint8_t*)&priv->ctrlreq,
+ USB_SIZEOF_CTRLREQ);
+
+ /* Was this an IN or an OUT SETUP packet. If it is an OUT SETUP,
+ * then we need to wait for the completion of the data phase to
+ * process the setup command. If it is an IN SETUP packet, then
+ * we must processing the command BEFORE we enter the DATA phase.
+ *
+ * If the data associated with the OUT SETUP packet is zero length,
+ * then, of course, we don't need to wait.
+ */
+
+ datlen = GETUINT16(priv->ctrlreq.len);
+ if (USB_REQ_ISOUT(priv->ctrlreq.type) && datlen > 0)
+ {
+ /* Wait for the data phase. */
+
+ priv->ep0state = EP0STATE_SETUP_OUT;
+ }
+ else
+ {
+ /* We can process the setup data as soon as SETUP done word is
+ * popped of the RxFIFO.
+ */
+
+ priv->ep0state = EP0STATE_SETUP_READY;
+ }
+ }
+ break;
+
+ default:
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS),
+ (regval & OTGFS_GRXSTSD_PKTSTS_MASK) >> OTGFS_GRXSTSD_PKTSTS_SHIFT);
+ }
+ break;
+ }
+
+ /* Enable the Rx Status Queue Level interrupt */
+
+ regval = stm32_getreg(STM32_OTGFS_GINTMSK);
+ regval |= OTGFS_GINT_RXFLVL;
+ stm32_putreg(regval, STM32_OTGFS_GINTMSK);
+}
+
+/*******************************************************************************
+ * Name: stm32_enuminterrupt
+ *
+ * Description:
+ * Enumeration done interrupt
+ *
+ *******************************************************************************/
+
+static inline void stm32_enuminterrupt(FAR struct stm32_usbdev_s *priv)
+{
+ uint32_t regval;
+
+ /* Activate EP0 */
+
+ stm32_ep0in_activate();
+
+ /* Set USB turn-around time for the full speed device with internal PHY interface. */
+
+ regval = stm32_getreg(STM32_OTGFS_GUSBCFG);
+ regval &= ~OTGFS_GUSBCFG_TRDT_MASK;
+ regval |= OTGFS_GUSBCFG_TRDT(5);
+ stm32_putreg(regval, STM32_OTGFS_GUSBCFG);
+}
+
+/*******************************************************************************
+ * Name: stm32_isocininterrupt
+ *
+ * Description:
+ * Incomplete isochronous IN transfer interrupt. Assertion of the incomplete
+ * isochronous IN transfer interrupt indicates an incomplete isochronous IN
+ * transfer on at least one of the isochronous IN endpoints.
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+static inline void stm32_isocininterrupt(FAR struct stm32_usbdev_s *priv)
+{
+ int i;
+
+ /* The application must read the endpoint control register for all isochronous
+ * IN endpoints to detect endpoints with incomplete IN data transfers.
+ */
+
+ for (i = 0; i < STM32_NENDPOINTS; i++)
+ {
+ /* Is this an isochronous IN endpoint? */
+
+ privep = &priv->epin[i];
+ if (privep->eptype != USB_EP_ATTR_XFER_ISOC)
+ {
+ /* No... keep looking */
+
+ continue;
+ }
+
+ /* Is there an active read request on the isochronous OUT endpoint? */
+
+ if (!privep->active)
+ {
+ /* No.. the endpoint is not actively transmitting data */
+
+ continue;
+ }
+
+ /* Check if this is the endpoint that had the incomplete transfer */
+
+ regaddr = STM32_OTGFS_DIEPCTL(privep->epphy);
+ doepctl = stm32_getreg(regaddr);
+ dsts = stm32_getreg(STM32_OTGFS_DSTS);
+
+ /* EONUM = 0:even frame, 1:odd frame
+ * SOFFN = Frame number of the received SOF
+ */
+
+ eonum = ((doepctl & OTGFS_DIEPCTL_EONUM) != 0);
+ soffn = ((dsts & OTGFS_DSTS_SOFFN0) != 0);
+
+ if (eonum != soffn)
+ {
+ /* Not this endpoint */
+
+ continue;
+ }
+
+ /* For isochronous IN endpoints with incomplete transfers,
+ * the application must discard the data in the memory and
+ * disable the endpoint.
+ */
+
+ stm32_req_complete(privep, -EIO);
+#warning "Will clear OTGFS_DIEPCTL_USBAEP too"
+ stm32_epin_disable(privep);
+ break;
+ }
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_isocoutinterrupt
+ *
+ * Description:
+ * Incomplete periodic transfer interrupt
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+static inline void stm32_isocoutinterrupt(FAR struct stm32_usbdev_s *priv)
+{
+ FAR struct stm32_ep_s *privep;
+ FAR struct stm32_req_s *privreq;
+ uint32_t regaddr;
+ uint32_t doepctl;
+ uint32_t dsts;
+ bool eonum;
+ bool soffn;
+
+ /* When it receives an IISOOXFR interrupt, the application must read the
+ * control registers of all isochronous OUT endpoints to determine which
+ * endpoints had an incomplete transfer in the current microframe. An
+ * endpoint transfer is incomplete if both the following conditions are true:
+ *
+ * DOEPCTLx:EONUM = DSTS:SOFFN[0], and
+ * DOEPCTLx:EPENA = 1
+ */
+
+ for (i = 0; i < STM32_NENDPOINTS; i++)
+ {
+ /* Is this an isochronous OUT endpoint? */
+
+ privep = &priv->epout[i];
+ if (privep->eptype != USB_EP_ATTR_XFER_ISOC)
+ {
+ /* No... keep looking */
+
+ continue;
+ }
+
+ /* Is there an active read request on the isochronous OUT endpoint? */
+
+ if (!privep->active)
+ {
+ /* No.. the endpoint is not actively transmitting data */
+
+ continue;
+ }
+
+ /* Check if this is the endpoint that had the incomplete transfer */
+
+ regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
+ doepctl = stm32_getreg(regaddr);
+ dsts = stm32_getreg(STM32_OTGFS_DSTS);
+
+ /* EONUM = 0:even frame, 1:odd frame
+ * SOFFN = Frame number of the received SOF
+ */
+
+ eonum = ((doepctl & OTGFS_DOEPCTL_EONUM) != 0);
+ soffn = ((dsts & OTGFS_DSTS_SOFFN0) != 0);
+
+ if (eonum != soffn)
+ {
+ /* Not this endpoint */
+
+ continue;
+ }
+
+ /* For isochronous OUT endpoints with incomplete transfers,
+ * the application must discard the data in the memory and
+ * disable the endpoint.
+ */
+
+ stm32_req_complete(privep, -EIO);
+#warning "Will clear OTGFS_DOEPCTL_USBAEP too"
+ stm32_epout_disable(privep);
+ break;
+ }
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_sessioninterrupt
+ *
+ * Description:
+ * Session request/new session detected interrupt
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_USBDEV_VBUSSENSING
+static inline void stm32_sessioninterrupt(FAR struct stm32_usbdev_s *priv)
+{
+#warning "Missing logic"
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_otginterrupt
+ *
+ * Description:
+ * OTG interrupt
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_USBDEV_VBUSSENSING
+static inline void stm32_otginterrupt(FAR struct stm32_usbdev_s *priv)
+{
+ uint32_t regval;
+
+ /* Check for session end detected */
+
+ regval = stm32_getreg(STM32_OTGFS_GOTGINT);
+ if ((regval & OTGFS_GOTGINT_SEDET) != 0)
+ {
+#warning "Missing logic"
+ }
+
+ /* Clear OTG interrupt */
+
+ stm32_putreg(retval, STM32_OTGFS_GOTGINT);
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_usbinterrupt
+ *
+ * Description:
+ * USB interrupt handler
+ *
+ *******************************************************************************/
+
+static int stm32_usbinterrupt(int irq, FAR void *context)
+{
+ /* At present, there is only a single OTG FS device support. Hence it is
+ * pre-allocated as g_otgfsdev. However, in most code, the private data
+ * structure will be referenced using the 'priv' pointer (rather than the
+ * global data) in order to simplify any future support for multiple devices.
+ */
+
+ FAR struct stm32_usbdev_s *priv = &g_otgfsdev;
+ uint32_t regval;
+
+ usbtrace(TRACE_INTENTRY(STM32_TRACEINTID_USB), 0);
+
+ /* Assure that we are in device mode */
+
+ DEBUGASSERT((stm32_getreg(STM32_OTGFS_GINTSTS) & OTGFS_GINTSTS_CMOD) == OTGFS_GINTSTS_DEVMODE);
+
+ /* Get the state of all enabled interrupts. We will do this repeatedly
+ * some interrupts (like RXFLVL) will generate additional interrupting
+ * events.
+ */
+
+ for (;;)
+ {
+ /* Get the set of pending, un-masked interrupts */
+
+ regval = stm32_getreg(STM32_OTGFS_GINTSTS);
+ regval &= stm32_getreg(STM32_OTGFS_GINTMSK);
+
+ /* Break out of the loop when there are no further pending (and
+ * unmasked) interrupts to be processes.
+ */
+
+ if (regval == 0)
+ {
+ break;
+ }
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_INTPENDING), (uint16_t)regval);
+
+ /* OUT endpoint interrupt. The core sets this bit to indicate that an
+ * interrupt is pending on one of the OUT endpoints of the core.
+ */
+
+ if ((regval & OTGFS_GINT_OEP) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUT), (uint16_t)regval);
+ stm32_epout_interrupt(priv);
+ stm32_putreg(OTGFS_GINT_OEP, STM32_OTGFS_GINTSTS);
+ }
+
+ /* IN endpoint interrupt. The core sets this bit to indicate that
+ * an interrupt is pending on one of the IN endpoints of the core.
+ */
+
+ if ((regval & OTGFS_GINT_IEP) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN), (uint16_t)regval);
+ stm32_epin_interrupt(priv);
+ stm32_putreg(OTGFS_GINT_IEP, STM32_OTGFS_GINTSTS);
+ }
+
+ /* Host/device mode mismatch error interrupt */
+
+#ifdef CONFIG_DEBUG_USB
+ if ((regval & OTGFS_GINT_MMIS) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_MISMATCH), (uint16_t)regval);
+ stm32_putreg(OTGFS_GINT_MMIS, STM32_OTGFS_GINTSTS);
+ }
+#endif
+
+ /* Resume/remote wakeup detected interrupt */
+
+ if ((regval & OTGFS_GINT_WKUP) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_WAKEUP), (uint16_t)regval);
+ stm32_resumeinterrupt(priv);
+ stm32_putreg(OTGFS_GINT_WKUP, STM32_OTGFS_GINTSTS);
+ }
+
+ /* USB suspend interrupt */
+
+ if ((regval & OTGFS_GINT_USBSUSP) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SUSPEND), (uint16_t)regval);
+ stm32_suspendinterrupt(priv);
+ stm32_putreg(OTGFS_GINT_USBSUSP, STM32_OTGFS_GINTSTS);
+ }
+
+ /* Start of frame interrupt */
+
+#ifdef CONFIG_USBDEV_SOFINTERRUPT
+ if ((regval & OTGFS_GINT_SOF) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SOF), (uint16_t)regval);
+ stm32_putreg(OTGFS_GINT_SOF, STM32_OTGFS_GINTSTS);
+ }
+#endif
+
+ /* RxFIFO non-empty interrupt. Indicates that there is at least one
+ * packet pending to be read from the RxFIFO.
+ */
+
+ if ((regval & OTGFS_GINT_RXFLVL) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_RXFIFO), (uint16_t)regval);
+ stm32_rxinterrupt(priv);
+ stm32_putreg(OTGFS_GINT_RXFLVL, STM32_OTGFS_GINTSTS);
+ }
+
+ /* USB reset interrupt */
+
+ if ((regval & OTGFS_GINT_USBRST) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DEVRESET), (uint16_t)regval);
+
+ /* Perform the device reset */
+
+ stm32_usbreset(priv);
+ usbtrace(TRACE_INTEXIT(STM32_TRACEINTID_USB), 0);
+ stm32_putreg(OTGFS_GINT_USBRST, STM32_OTGFS_GINTSTS);
+ return OK;
+ }
+
+ /* Enumeration done interrupt */
+
+ if ((regval & OTGFS_GINT_ENUMDNE) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_ENUMDNE), (uint16_t)regval);
+ stm32_enuminterrupt(priv);
+ stm32_putreg(OTGFS_GINT_ENUMDNE, STM32_OTGFS_GINTSTS);
+ }
+
+ /* Incomplete isochronous IN transfer interrupt. When the core finds
+ * non-empty any of the isochronous IN endpoint FIFOs scheduled for
+ * the current frame non-empty, the core generates an IISOIXFR
+ * interrupt.
+ */
+
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+ if ((regval & OTGFS_GINT_IISOIXFR) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_IISOIXFR), (uint16_t)regval);
+ stm32_isocininterrupt(priv);
+ stm32_putreg(OTGFS_GINT_IISOIXFR, STM32_OTGFS_GINTSTS);
+ }
+
+ /* Incomplete isochronous OUT transfer. For isochronous OUT
+ * endpoints, the XFRC interrupt may not always be asserted. If the
+ * core drops isochronous OUT data packets, the application could fail
+ * to detect the XFRC interrupt. The incomplete Isochronous OUT data
+ * interrupt indicates that an XFRC interrupt was not asserted on at
+ * least one of the isochronous OUT endpoints. At this point, the
+ * endpoint with the incomplete transfer remains enabled, but no active
+ * transfers remain in progress on this endpoint on the USB.
+ */
+
+ if ((regval & OTGFS_GINT_IISOOXFR) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_IISOOXFR), (uint16_t)regval);
+ stm32_isocoutinterrupt(priv);
+ stm32_putreg(OTGFS_GINT_IISOOXFR, STM32_OTGFS_GINTSTS);
+ }
+#endif
+
+ /* Session request/new session detected interrupt */
+
+#ifdef CONFIG_USBDEV_VBUSSENSING
+ if ((regval & OTGFS_GINT_SRQ) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SRQ), (uint16_t)regval);
+ stm32_sessioninterrupt(priv);
+ stm32_putreg(OTGFS_GINT_SRQ, STM32_OTGFS_GINTSTS);
+ }
+
+ /* OTG interrupt */
+
+ if ((regval & OTGFS_GINT_OTG) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OTG), (uint16_t)regval);
+ stm32_otginterrupt(priv);
+ stm32_putreg(OTGFS_GINT_OTG, STM32_OTGFS_GINTSTS);
+ }
+#endif
+ }
+
+ usbtrace(TRACE_INTEXIT(STM32_TRACEINTID_USB), 0);
+ return OK;
+}
+
+/*******************************************************************************
+ * Endpoint operations
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: stm32_enablegonak
+ *
+ * Description:
+ * Enable global OUT NAK mode
+ *
+ *******************************************************************************/
+
+static void stm32_enablegonak(FAR struct stm32_ep_s *privep)
+{
+ uint32_t regval;
+
+ /* First, make sure that there is no GNOAKEFF interrupt pending. */
+
+#if 0
+ stm32_putreg(OTGFS_GINT_GONAKEFF, STM32_OTGFS_GINTSTS);
+#endif
+
+ /* Enable Global OUT NAK mode in the core. */
+
+ regval = stm32_getreg(STM32_OTGFS_DCTL);
+ regval |= OTGFS_DCTL_SGONAK;
+ stm32_putreg(regval, STM32_OTGFS_DCTL);
+
+#if 0
+ /* Wait for the GONAKEFF interrupt that indicates that the OUT NAK
+ * mode is in effect. When the interrupt handler pops the OUTNAK word
+ * from the RxFIFO, the core sets the GONAKEFF interrupt.
+ */
+
+ while ((stm32_getreg(STM32_OTGFS_GINTSTS) & OTGFS_GINT_GONAKEFF) == 0);
+ stm32_putreg(OTGFS_GINT_GONAKEFF, STM32_OTGFS_GINTSTS);
+
+#else
+ /* Since we are in the interrupt handler, we cannot wait inline for the
+ * GONAKEFF because it cannot occur until service th RXFLVL global interrupt
+ * and pop the OUTNAK word from the RxFIFO.
+ *
+ * Perhaps it is sufficient to wait for Global OUT NAK status to be reported
+ * in OTGFS DCTL register?
+ */
+
+ while ((stm32_getreg(STM32_OTGFS_DCTL) & OTGFS_DCTL_GONSTS) == 0);
+#endif
+}
+
+/*******************************************************************************
+ * Name: stm32_disablegonak
+ *
+ * Description:
+ * Disable global OUT NAK mode
+ *
+ *******************************************************************************/
+
+static void stm32_disablegonak(FAR struct stm32_ep_s *privep)
+{
+ uint32_t regval;
+
+ /* Set the "Clear the Global OUT NAK bit" to disable global OUT NAK mode */
+
+ regval = stm32_getreg(STM32_OTGFS_DCTL);
+ regval |= OTGFS_DCTL_CGONAK;
+ stm32_putreg(regval, STM32_OTGFS_DCTL);
+}
+
+/*******************************************************************************
+ * Name: stm32_epout_configure
+ *
+ * Description:
+ * Configure an OUT endpoint, making it usable
+ *
+ * Input Parameters:
+ * privep - a pointer to an internal endpoint structure
+ * eptype - The type of the endpoint
+ * maxpacket - The max packet size of the endpoint
+ *
+ *******************************************************************************/
+
+static int stm32_epout_configure(FAR struct stm32_ep_s *privep, uint8_t eptype,
+ uint16_t maxpacket)
+{
+ uint32_t mpsiz;
+ uint32_t regaddr;
+ uint32_t regval;
+
+ usbtrace(TRACE_EPCONFIGURE, privep->epphy);
+
+ /* For EP0, the packet size is encoded */
+
+ if (privep->epphy == EP0)
+ {
+ DEBUGASSERT(eptype == USB_EP_ATTR_XFER_CONTROL);
+
+ /* Map the size in bytes to the encoded value in the register */
+
+ switch (maxpacket)
+ {
+ case 8:
+ mpsiz = OTGFS_DOEPCTL0_MPSIZ_8;
+ break;
+
+ case 16:
+ mpsiz = OTGFS_DOEPCTL0_MPSIZ_16;
+ break;
+
+ case 32:
+ mpsiz = OTGFS_DOEPCTL0_MPSIZ_32;
+ break;
+
+ case 64:
+ mpsiz = OTGFS_DOEPCTL0_MPSIZ_64;
+ break;
+
+ default:
+ udbg("Unsupported maxpacket: %d\n", maxpacket);
+ return -EINVAL;
+ }
+ }
+
+ /* For other endpoints, the packet size is in bytes */
+
+ else
+ {
+ mpsiz = (maxpacket << OTGFS_DOEPCTL_MPSIZ_SHIFT);
+ }
+
+ /* If the endpoint is already active don't change the endpoint control
+ * register.
+ */
+
+ regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ if ((regval & OTGFS_DOEPCTL_USBAEP) == 0)
+ {
+ regval &= ~(OTGFS_DOEPCTL_MPSIZ_MASK | OTGFS_DIEPCTL_EPTYP_MASK | OTGFS_DIEPCTL_TXFNUM_MASK);
+ regval |= mpsiz;
+ regval |= (eptype << OTGFS_DOEPCTL_EPTYP_SHIFT);
+ regval |= (eptype << OTGFS_DIEPCTL_TXFNUM_SHIFT);
+ regval |= (OTGFS_DOEPCTL_SD0PID | OTGFS_DOEPCTL_USBAEP);
+ stm32_putreg(regval, regaddr);
+
+ /* Save the endpoint configuration */
+
+ privep->ep.maxpacket = maxpacket;
+ privep->eptype = eptype;
+ privep->stalled = false;
+ }
+
+ /* Enable the interrupt for this endpoint */
+
+ regval = stm32_getreg(STM32_OTGFS_DAINTMSK);
+ regval |= OTGFS_DAINT_OEP(privep->epphy);
+ stm32_putreg(regval, STM32_OTGFS_DAINTMSK);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_epin_configure
+ *
+ * Description:
+ * Configure an IN endpoint, making it usable
+ *
+ * Input Parameters:
+ * privep - a pointer to an internal endpoint structure
+ * eptype - The type of the endpoint
+ * maxpacket - The max packet size of the endpoint
+ *
+ *******************************************************************************/
+
+static int stm32_epin_configure(FAR struct stm32_ep_s *privep, uint8_t eptype,
+ uint16_t maxpacket)
+{
+ uint32_t mpsiz;
+ uint32_t regaddr;
+ uint32_t regval;
+
+ usbtrace(TRACE_EPCONFIGURE, privep->epphy);
+
+ /* For EP0, the packet size is encoded */
+
+ if (privep->epphy == EP0)
+ {
+ DEBUGASSERT(eptype == USB_EP_ATTR_XFER_CONTROL);
+
+ /* Map the size in bytes to the encoded value in the register */
+
+ switch (maxpacket)
+ {
+ case 8:
+ mpsiz = OTGFS_DIEPCTL0_MPSIZ_8;
+ break;
+
+ case 16:
+ mpsiz = OTGFS_DIEPCTL0_MPSIZ_16;
+ break;
+
+ case 32:
+ mpsiz = OTGFS_DIEPCTL0_MPSIZ_32;
+ break;
+
+ case 64:
+ mpsiz = OTGFS_DIEPCTL0_MPSIZ_64;
+ break;
+
+ default:
+ udbg("Unsupported maxpacket: %d\n", maxpacket);
+ return -EINVAL;
+ }
+ }
+
+ /* For other endpoints, the packet size is in bytes */
+
+ else
+ {
+ mpsiz = (maxpacket << OTGFS_DIEPCTL_MPSIZ_SHIFT);
+ }
+
+
+ /* If the endpoint is already active don't change the endpoint control
+ * register.
+ */
+
+ regaddr = STM32_OTGFS_DIEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ if ((regval & OTGFS_DIEPCTL_USBAEP) == 0)
+ {
+ regval &= ~(OTGFS_DIEPCTL_MPSIZ_MASK | OTGFS_DIEPCTL_EPTYP_MASK | OTGFS_DIEPCTL_TXFNUM_MASK);
+ regval |= mpsiz;
+ regval |= (eptype << OTGFS_DIEPCTL_EPTYP_SHIFT);
+ regval |= (eptype << OTGFS_DIEPCTL_TXFNUM_SHIFT);
+ regval |= (OTGFS_DIEPCTL_SD0PID | OTGFS_DIEPCTL_USBAEP);
+ stm32_putreg(regval, regaddr);
+
+ /* Save the endpoint configuration */
+
+ privep->ep.maxpacket = maxpacket;
+ privep->eptype = eptype;
+ privep->stalled = false;
+ }
+
+ /* Enable the interrupt for this endpoint */
+
+ regval = stm32_getreg(STM32_OTGFS_DAINTMSK);
+ regval |= OTGFS_DAINT_IEP(privep->epphy);
+ stm32_putreg(regval, STM32_OTGFS_DAINTMSK);
+
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_configure
+ *
+ * Description:
+ * Configure endpoint, making it usable
+ *
+ * Input Parameters:
+ * ep - the struct usbdev_ep_s instance obtained from allocep()
+ * desc - A struct usb_epdesc_s instance describing the endpoint
+ * last - true if this this last endpoint to be configured. Some hardware
+ * needs to take special action when all of the endpoints have been
+ * configured.
+ *
+ *******************************************************************************/
+
+static int stm32_ep_configure(FAR struct usbdev_ep_s *ep,
+ FAR const struct usb_epdesc_s *desc,
+ bool last)
+{
+ FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep;
+ uint16_t maxpacket;
+ uint8_t eptype;
+ int ret;
+
+ usbtrace(TRACE_EPCONFIGURE, privep->epphy);
+ DEBUGASSERT(desc->addr == ep->eplog);
+
+ /* Initialize EP capabilities */
+
+ maxpacket = GETUINT16(desc->mxpacketsize);
+ eptype = desc->attr & USB_EP_ATTR_XFERTYPE_MASK;
+
+ /* Setup Endpoint Control Register */
+
+ if (privep->isin)
+ {
+ ret = stm32_epin_configure(privep, eptype, maxpacket);
+ }
+ else
+ {
+ ret = stm32_epout_configure(privep, eptype, maxpacket);
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep0_configure
+ *
+ * Description:
+ * Reset Usb engine
+ *
+ *******************************************************************************/
+
+static void stm32_ep0_configure(FAR struct stm32_usbdev_s *priv)
+{
+ /* Enable EP0 IN and OUT */
+
+ (void)stm32_epin_configure(&priv->epin[EP0], USB_EP_ATTR_XFER_CONTROL,
+ CONFIG_USBDEV_EP0_MAXSIZE);
+ (void)stm32_epout_configure(&priv->epout[EP0], USB_EP_ATTR_XFER_CONTROL,
+ CONFIG_USBDEV_EP0_MAXSIZE);
+}
+
+/*******************************************************************************
+ * Name: stm32_epout_disable
+ *
+ * Description:
+ * Diable an OUT endpoint will no longer be used
+ *
+ *******************************************************************************/
+
+static void stm32_epout_disable(FAR struct stm32_ep_s *privep)
+{
+ uint32_t regaddr;
+ uint32_t regval;
+ irqstate_t flags;
+
+ usbtrace(TRACE_EPDISABLE, privep->epphy);
+
+ /* Is this an IN or an OUT endpoint */
+
+ /* Before disabling any OUT endpoint, the application must enable
+ * Global OUT NAK mode in the core.
+ */
+
+ flags = irqsave();
+ stm32_enablegonak(privep);
+
+ /* Disable the required OUT endpoint by setting the EPDIS and SNAK bits
+ * int DOECPTL register.
+ */
+
+ regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ regval &= ~OTGFS_DOEPCTL_USBAEP;
+ regval |= (OTGFS_DOEPCTL_EPDIS | OTGFS_DOEPCTL_SNAK);
+ stm32_putreg(regval, regaddr);
+
+ /* Wait for the EPDISD interrupt which indicates that the OUT
+ * endpoint is completely disabled.
+ */
+
+#if 0 /* Doesn't happen */
+ regaddr = STM32_OTGFS_DOEPINT(privep->epphy);
+ while ((stm32_getreg(regaddr) & OTGFS_DOEPINT_EPDISD) == 0);
+#else
+ /* REVISIT: */
+ up_mdelay(50);
+#endif
+
+ /* Then disble the Global OUT NAK mode to continue receiving data
+ * from other non-disabled OUT endpoints.
+ */
+
+ stm32_disablegonak(privep);
+
+ /* Disable endpoint interrupts */
+
+ regval = stm32_getreg(STM32_OTGFS_DAINTMSK);
+ regval &= ~OTGFS_DAINT_OEP(privep->epphy);
+ stm32_putreg(regval, STM32_OTGFS_DAINTMSK);
+
+ /* Cancel any queued read requests */
+
+ stm32_req_cancel(privep, -ESHUTDOWN);
+
+ irqrestore(flags);
+}
+
+/*******************************************************************************
+ * Name: stm32_epin_disable
+ *
+ * Description:
+ * Diable an IN endpoint will no longer be used
+ *
+ *******************************************************************************/
+
+static void stm32_epin_disable(FAR struct stm32_ep_s *privep)
+{
+ uint32_t regaddr;
+ uint32_t regval;
+ irqstate_t flags;
+
+ usbtrace(TRACE_EPDISABLE, privep->epphy);
+
+ /* Make sure that there is no pending IPEPNE interrupt (because we are
+ * to poll this bit below).
+ */
+
+ stm32_putreg(OTGFS_DIEPINT_INEPNE, STM32_OTGFS_DIEPINT(privep->epphy));
+
+ /* Set the endpoint in NAK mode */
+
+ regaddr = STM32_OTGFS_DIEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ regval &= ~OTGFS_DIEPCTL_USBAEP;
+ regval |= (OTGFS_DIEPCTL_EPDIS | OTGFS_DIEPCTL_SNAK);
+ stm32_putreg(regval, regaddr);
+
+ /* Wait for the INEPNE interrupt that indicates that we are now in NAK mode */
+
+ regaddr = STM32_OTGFS_DIEPINT(privep->epphy);
+ while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_INEPNE) == 0);
+ stm32_putreg(OTGFS_DIEPINT_INEPNE, regaddr);
+
+ /* Deactivate and disable the endpoint by setting the EPIS and SNAK bits
+ * the DIEPCTLx register.
+ */
+
+ flags = irqsave();
+ regaddr = STM32_OTGFS_DIEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ regval &= ~OTGFS_DIEPCTL_USBAEP;
+ regval |= (OTGFS_DIEPCTL_EPDIS | OTGFS_DIEPCTL_SNAK);
+ stm32_putreg(regval, regaddr);
+
+ /* Wait for the EPDISD interrupt which indicates that the IN
+ * endpoint is completely disabled.
+ */
+
+ regaddr = STM32_OTGFS_DIEPINT(privep->epphy);
+ while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_EPDISD) == 0);
+
+ /* Flush any data remaining in the TxFIFO */
+
+ stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_D(privep->epphy));
+
+ /* Disable endpoint interrupts */
+
+ regval = stm32_getreg(STM32_OTGFS_DAINTMSK);
+ regval &= ~OTGFS_DAINT_IEP(privep->epphy);
+ stm32_putreg(regval, STM32_OTGFS_DAINTMSK);
+
+ /* Cancel any queued write requests */
+
+ stm32_req_cancel(privep, -ESHUTDOWN);
+
+ irqrestore(flags);
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_disable
+ *
+ * Description:
+ * The endpoint will no longer be used
+ *
+ *******************************************************************************/
+
+static int stm32_ep_disable(FAR struct usbdev_ep_s *ep)
+{
+ FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep;
+
+#ifdef CONFIG_DEBUG
+ if (!ep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+ usbtrace(TRACE_EPDISABLE, privep->epphy);
+
+ /* Is this an IN or an OUT endpoint */
+
+ if (privep->isin)
+ {
+ /* Disable the IN endpoint */
+
+ stm32_epin_disable(privep);
+ }
+ else
+ {
+ /* Disable the OUT endpoint */
+
+ stm32_epout_disable(privep);
+ }
+
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_allocreq
+ *
+ * Description:
+ * Allocate an I/O request
+ *
+ *******************************************************************************/
+
+static FAR struct usbdev_req_s *stm32_ep_allocreq(FAR struct usbdev_ep_s *ep)
+{
+ FAR struct stm32_req_s *privreq;
+
+#ifdef CONFIG_DEBUG
+ if (!ep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return NULL;
+ }
+#endif
+ usbtrace(TRACE_EPALLOCREQ, ((FAR struct stm32_ep_s *)ep)->epphy);
+
+ privreq = (FAR struct stm32_req_s *)malloc(sizeof(struct stm32_req_s));
+ if (!privreq)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_ALLOCFAIL), 0);
+ return NULL;
+ }
+
+ memset(privreq, 0, sizeof(struct stm32_req_s));
+ return &privreq->req;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_freereq
+ *
+ * Description:
+ * Free an I/O request
+ *
+ *******************************************************************************/
+
+static void stm32_ep_freereq(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
+{
+ FAR struct stm32_req_s *privreq = (FAR struct stm32_req_s *)req;
+
+#ifdef CONFIG_DEBUG
+ if (!ep || !req)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return;
+ }
+#endif
+
+ usbtrace(TRACE_EPFREEREQ, ((FAR struct stm32_ep_s *)ep)->epphy);
+ free(privreq);
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_allocbuffer
+ *
+ * Description:
+ * Allocate an I/O buffer
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_ARCH_USBDEV_DMA
+static void *stm32_ep_allocbuffer(FAR struct usbdev_ep_s *ep, unsigned bytes)
+{
+ usbtrace(TRACE_EPALLOCBUFFER, privep->epphy);
+ return malloc(bytes)
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_ep_freebuffer
+ *
+ * Description:
+ * Free an I/O buffer
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_LPC313x_USBDEV_DMA
+static void stm32_ep_freebuffer(FAR struct usbdev_ep_s *ep, FAR void *buf)
+{
+ usbtrace(TRACE_EPFREEBUFFER, privep->epphy);
+ free(buf);
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_ep_submit
+ *
+ * Description:
+ * Submit an I/O request to the endpoint
+ *
+ *******************************************************************************/
+
+static int stm32_ep_submit(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
+{
+ FAR struct stm32_req_s *privreq = (FAR struct stm32_req_s *)req;
+ FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep;
+ FAR struct stm32_usbdev_s *priv;
+ irqstate_t flags;
+ int ret = OK;
+
+ /* Some sanity checking */
+
+#ifdef CONFIG_DEBUG
+ if (!req || !req->callback || !req->buf || !ep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ ullvdbg("req=%p callback=%p buf=%p ep=%p\n", req, req->callback, req->buf, ep);
+ return -EINVAL;
+ }
+#endif
+
+ usbtrace(TRACE_EPSUBMIT, privep->epphy);
+ priv = privep->dev;
+
+#ifdef CONFIG_DEBUG
+ if (!priv->driver)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_NOTCONFIGURED), priv->usbdev.speed);
+ return -ESHUTDOWN;
+ }
+#endif
+
+ /* Handle the request from the class driver */
+
+ req->result = -EINPROGRESS;
+ req->xfrd = 0;
+
+ /* Disable Interrupts */
+
+ flags = irqsave();
+
+ /* If we are stalled, then drop all requests on the floor */
+
+ if (privep->stalled)
+ {
+ ret = -EBUSY;
+ }
+ else
+ {
+ /* Add the new request to the request queue for the endpoint. */
+
+ if (stm32_req_addlast(privep, privreq) && !privep->active)
+ {
+ /* If a request was added to an IN endpoint, then attempt to send
+ * the request data buffer now.
+ */
+
+ if (privep->isin)
+ {
+ usbtrace(TRACE_INREQQUEUED(privep->epphy), privreq->req.len);
+
+ /* If the endpoint is not busy with another write request,
+ * then process the newly received write request now.
+ */
+
+ if (!privep->active)
+ {
+ stm32_epin_request(priv, privep);
+ }
+ }
+
+ /* If the request was added to an OUT endoutput, then attempt to
+ * setup a read into the request data buffer now (this will, of
+ * course, fail if there is already a read in place).
+ */
+
+ else
+ {
+ usbtrace(TRACE_OUTREQQUEUED(privep->epphy), privreq->req.len);
+ stm32_epout_request(priv, privep);
+ }
+ }
+ }
+
+ irqrestore(flags);
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_cancel
+ *
+ * Description:
+ * Cancel an I/O request previously sent to an endpoint
+ *
+ *******************************************************************************/
+
+static int stm32_ep_cancel(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
+{
+ FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep;
+ FAR struct stm32_usbdev_s *priv;
+ irqstate_t flags;
+
+#ifdef CONFIG_DEBUG
+ if (!ep || !req)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+
+ usbtrace(TRACE_EPCANCEL, privep->epphy);
+ priv = privep->dev;
+
+ flags = irqsave();
+
+ /* FIXME: if the request is the first, then we need to flush the EP
+ * otherwise just remove it from the list
+ *
+ * but ... all other implementations cancel all requests ...
+ */
+
+ stm32_req_cancel(privep, -ESHUTDOWN);
+ irqrestore(flags);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_epout_setstall
+ *
+ * Description:
+ * Stall an OUT endpoint
+ *
+ *******************************************************************************/
+
+static int stm32_epout_setstall(FAR struct stm32_ep_s *privep)
+{
+#if 1
+ /* This implementation follows the requirements from the STM32 F4 reference
+ * manual.
+ */
+
+ uint32_t regaddr;
+ uint32_t regval;
+
+ /* Put the core in the Global OUT NAK mode */
+
+ stm32_enablegonak(privep);
+
+ /* Disable and STALL the OUT endpoint by setting the EPDIS and STALL bits
+ * in the DOECPTL register.
+ */
+
+ regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ regval |= (OTGFS_DOEPCTL_EPDIS | OTGFS_DOEPCTL_STALL);
+ stm32_putreg(regval, regaddr);
+
+ /* Wait for the EPDISD interrupt which indicates that the OUT
+ * endpoint is completely disabled.
+ */
+
+#if 0 /* Doesn't happen */
+ regaddr = STM32_OTGFS_DOEPINT(privep->epphy);
+ while ((stm32_getreg(regaddr) & OTGFS_DOEPINT_EPDISD) == 0);
+#else
+ /* REVISIT: */
+ up_mdelay(50);
+#endif
+
+ /* Disable Global OUT NAK mode */
+
+ stm32_disablegonak(privep);
+
+ /* The endpoint is now stalled */
+
+ privep->stalled = true;
+ return OK;
+#else
+ /* This implementation follows the STMicro code example. */
+ /* REVISIT: */
+
+ uint32_t regaddr;
+ uint32_t regval;
+
+ /* Stall the OUT endpoint by setting the STALL bit in the DOECPTL register. */
+
+ regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+ regval |= OTGFS_DOEPCTL_STALL;
+ stm32_putreg(regval, regaddr);
+
+ /* The endpoint is now stalled */
+
+ privep->stalled = true;
+ return OK;
+#endif
+}
+
+/*******************************************************************************
+ * Name: stm32_epin_setstall
+ *
+ * Description:
+ * Stall an IN endpoint
+ *
+ *******************************************************************************/
+
+static int stm32_epin_setstall(FAR struct stm32_ep_s *privep)
+{
+ uint32_t regaddr;
+ uint32_t regval;
+
+ /* Get the IN endpoint device control register */
+
+ regaddr = STM32_OTGFS_DIEPCTL(privep->epphy);
+ regval = stm32_getreg(regaddr);
+
+ /* Is the endpoint enabled? */
+
+ if ((regval & OTGFS_DIEPCTL_EPENA) != 0)
+ {
+ /* Yes.. the endpoint is enabled, disable it */
+
+ regval = OTGFS_DIEPCTL_EPDIS;
+ }
+ else
+ {
+ regval = 0;
+ }
+
+ /* Then stall the endpoint */
+
+ regval |= OTGFS_DIEPCTL_STALL;
+ stm32_putreg(regval, regaddr);
+
+ /* The endpoint is now stalled */
+
+ privep->stalled = true;
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_setstall
+ *
+ * Description:
+ * Stall an endpoint
+ *
+ *******************************************************************************/
+
+static int stm32_ep_setstall(FAR struct stm32_ep_s *privep)
+{
+ usbtrace(TRACE_EPSTALL, privep->epphy);
+
+ /* Is this an IN endpoint? */
+
+ if (privep->isin == 1)
+ {
+ return stm32_epin_setstall(privep);
+ }
+ else
+ {
+ return stm32_epout_setstall(privep);
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_clrstall
+ *
+ * Description:
+ * Resume a stalled endpoint
+ *
+ *******************************************************************************/
+
+static int stm32_ep_clrstall(FAR struct stm32_ep_s *privep)
+{
+ uint32_t regaddr;
+ uint32_t regval;
+ uint32_t stallbit;
+ uint32_t data0bit;
+
+ usbtrace(TRACE_EPRESUME, privep->epphy);
+
+ /* Is this an IN endpoint? */
+
+ if (privep->isin == 1)
+ {
+ /* Clear the stall bit in the IN endpoint device control register */
+
+ regaddr = STM32_OTGFS_DIEPCTL(privep->epphy);
+ stallbit = OTGFS_DIEPCTL_STALL;
+ data0bit = OTGFS_DIEPCTL_SD0PID;
+ }
+ else
+ {
+ /* Clear the stall bit in the IN endpoint device control register */
+
+ regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
+ stallbit = OTGFS_DOEPCTL_STALL;
+ data0bit = OTGFS_DOEPCTL_SD0PID;
+ }
+
+ /* Clear the stall bit */
+
+ regval = stm32_getreg(regaddr);
+ regval &= ~stallbit;
+
+ /* Set the DATA0 pid for interrupt and bulk endpoints */
+
+ if (privep->eptype == USB_EP_ATTR_XFER_INT ||
+ privep->eptype == USB_EP_ATTR_XFER_BULK)
+ {
+ /* Writing this bit sets the DATA0 PID */
+
+ regval |= data0bit;
+ }
+
+ stm32_putreg(regval, regaddr);
+
+ /* The endpoint is no longer stalled */
+
+ privep->stalled = false;
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_stall
+ *
+ * Description:
+ * Stall or resume an endpoint
+ *
+ *******************************************************************************/
+
+static int stm32_ep_stall(FAR struct usbdev_ep_s *ep, bool resume)
+{
+ FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep;
+ irqstate_t flags;
+ int ret;
+
+ /* Set or clear the stall condition as requested */
+
+ flags = irqsave();
+ if (resume)
+ {
+ ret = stm32_ep_clrstall(privep);
+ }
+ else
+ {
+ ret = stm32_ep_setstall(privep);
+ }
+ irqrestore(flags);
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep0_stall
+ *
+ * Description:
+ * Stall endpoint 0
+ *
+ *******************************************************************************/
+
+static void stm32_ep0_stall(FAR struct stm32_usbdev_s *priv)
+{
+ stm32_epin_setstall(&priv->epin[EP0]);
+ stm32_epout_setstall(&priv->epout[EP0]);
+ priv->stalled = true;
+ stm32_ep0out_ctrlsetup(priv);
+}
+
+/*******************************************************************************
+ * Device operations
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: stm32_ep_alloc
+ *
+ * Description:
+ * Allocate an endpoint matching the parameters.
+ *
+ * Input Parameters:
+ * eplog - 7-bit logical endpoint number (direction bit ignored). Zero means
+ * that any endpoint matching the other requirements will suffice. The
+ * assigned endpoint can be found in the eplog field.
+ * in - true: IN (device-to-host) endpoint requested
+ * eptype - Endpoint type. One of {USB_EP_ATTR_XFER_ISOC, USB_EP_ATTR_XFER_BULK,
+ * USB_EP_ATTR_XFER_INT}
+ *
+ *******************************************************************************/
+
+static FAR struct usbdev_ep_s *stm32_ep_alloc(FAR struct usbdev_s *dev,
+ uint8_t eplog, bool in,
+ uint8_t eptype)
+{
+ FAR struct stm32_usbdev_s *priv = (FAR struct stm32_usbdev_s *)dev;
+ uint8_t epavail;
+ irqstate_t flags;
+ int epphy;
+ int epno = 0;
+
+ usbtrace(TRACE_DEVALLOCEP, (uint16_t)eplog);
+
+ /* Ignore any direction bits in the logical address */
+
+ epphy = USB_EPNO(eplog);
+
+ /* Get the set of available endpoints */
+
+ flags = irqsave();
+ epavail = priv->epavail;
+
+ /* A physical address of 0 means that any endpoint will do */
+
+ if (epphy > 0)
+ {
+ /* Otherwise, we will return the endpoint structure only for the requested
+ * 'logical' endpoint. All of the other checks will still be performed.
+ *
+ * First, verify that the logical endpoint is in the range supported by
+ * by the hardware.
+ */
+
+ if (epphy >= STM32_NENDPOINTS)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPNO), (uint16_t)epphy);
+ return NULL;
+ }
+
+ /* Remove all of the candidate endpoints from the bitset except for the
+ * this physical endpoint number.
+ */
+
+ epavail &= (1 << epphy);
+ }
+
+ /* Is there an available endpoint? */
+
+ if (epavail)
+ {
+ /* Yes.. Select the lowest numbered endpoint in the set of available
+ * endpoints.
+ */
+
+ for (epno = 1; epno < STM32_NENDPOINTS; epno++)
+ {
+ uint8_t bit = 1 << epno;
+ if ((epavail & bit) != 0)
+ {
+ /* Mark the endpoint no longer available */
+
+ priv->epavail &= ~(1 << epno);
+
+ /* And return the pointer to the standard endpoint structure */
+
+ irqrestore(flags);
+ return in ? &priv->epin[epno].ep : &priv->epout[epno].ep;
+ }
+ }
+
+ /* We should not get here */
+ }
+
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_NOEP), (uint16_t)eplog);
+ irqrestore(flags);
+ return NULL;
+}
+
+/*******************************************************************************
+ * Name: stm32_ep_free
+ *
+ * Description:
+ * Free the previously allocated endpoint
+ *
+ *******************************************************************************/
+
+static void stm32_ep_free(FAR struct usbdev_s *dev, FAR struct usbdev_ep_s *ep)
+{
+ FAR struct stm32_usbdev_s *priv = (FAR struct stm32_usbdev_s *)dev;
+ FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep;
+ irqstate_t flags;
+
+ usbtrace(TRACE_DEVFREEEP, (uint16_t)privep->epphy);
+
+ if (priv && privep)
+ {
+ /* Mark the endpoint as available */
+
+ flags = irqsave();
+ priv->epavail |= (1 << privep->epphy);
+ irqrestore(flags);
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_getframe
+ *
+ * Description:
+ * Returns the current frame number
+ *
+ *******************************************************************************/
+
+static int stm32_getframe(struct usbdev_s *dev)
+{
+ uint32_t regval;
+
+ usbtrace(TRACE_DEVGETFRAME, 0);
+
+ /* Return the last frame number of the last SOF detected by the hardware */
+
+ regval = stm32_getreg(STM32_OTGFS_DSTS);
+ return (int)((regval & OTGFS_DSTS_SOFFN_MASK) >> OTGFS_DSTS_SOFFN_SHIFT);
+}
+
+/*******************************************************************************
+ * Name: stm32_wakeup
+ *
+ * Description:
+ * Exit suspend mode.
+ *
+ *******************************************************************************/
+
+static int stm32_wakeup(struct usbdev_s *dev)
+{
+ FAR struct stm32_usbdev_s *priv = (FAR struct stm32_usbdev_s *)dev;
+ uint32_t regval;
+ irqstate_t flags;
+
+ usbtrace(TRACE_DEVWAKEUP, 0);
+
+ /* Is wakeup enabled? */
+
+ flags = irqsave();
+ if (priv->wakeup)
+ {
+ /* Yes... is the core suspended? */
+
+ regval = stm32_getreg(STM32_OTGFS_DSTS);
+ if ((regval & OTGFS_DSTS_SUSPSTS) != 0)
+ {
+ /* Re-start the PHY clock and un-gate USB core clock (HCLK) */
+
+#ifdef CONFIG_USBDEV_LOWPOWER
+ regval = stm32_getreg(STM32_OTGFS_PCGCCTL);
+ regval &= ~(OTGFS_PCGCCTL_STPPCLK | OTGFS_PCGCCTL_GATEHCLK);
+ stm32_putreg(regval, STM32_OTGFS_PCGCCTL);
+#endif
+
+ /* Activate Remote wakeup signaling */
+
+ regval = stm32_getreg(STM32_OTGFS_DCTL);
+ regval |= OTGFS_DCTL_RWUSIG;
+ stm32_putreg(regval, STM32_OTGFS_DCTL);
+ up_mdelay(5);
+ regval &= ~OTGFS_DCTL_RWUSIG;
+ stm32_putreg(regval, STM32_OTGFS_DCTL);
+ }
+ }
+
+ irqrestore(flags);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_selfpowered
+ *
+ * Description:
+ * Sets/clears the device selfpowered feature
+ *
+ *******************************************************************************/
+
+static int stm32_selfpowered(struct usbdev_s *dev, bool selfpowered)
+{
+ FAR struct stm32_usbdev_s *priv = (FAR struct stm32_usbdev_s *)dev;
+
+ usbtrace(TRACE_DEVSELFPOWERED, (uint16_t)selfpowered);
+
+#ifdef CONFIG_DEBUG
+ if (!dev)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -ENODEV;
+ }
+#endif
+
+ priv->selfpowered = selfpowered;
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_pullup
+ *
+ * Description:
+ * Software-controlled connect to/disconnect from USB host
+ *
+ *******************************************************************************/
+
+static int stm32_pullup(struct usbdev_s *dev, bool enable)
+{
+ uint32_t regval;
+
+ usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
+
+ irqstate_t flags = irqsave();
+ regval = stm32_getreg(STM32_OTGFS_DCTL);
+ if (enable)
+ {
+ /* Connect the device by clearing the soft disconnect bit in the DCTL
+ * register
+ */
+
+ regval &= ~OTGFS_DCTL_SDIS;
+ }
+ else
+ {
+ /* Connect the device by setting the soft disconnect bit in the DCTL
+ * register
+ */
+
+ regval |= OTGFS_DCTL_SDIS;
+ }
+
+ stm32_putreg(regval, STM32_OTGFS_DCTL);
+ up_mdelay(3);
+
+ irqrestore(flags);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_setaddress
+ *
+ * Description:
+ * Set the devices USB address
+ *
+ *******************************************************************************/
+
+static void stm32_setaddress(struct stm32_usbdev_s *priv, uint16_t address)
+{
+ uint32_t regval;
+
+ /* Set the device address in the DCFG register */
+
+ regval = stm32_getreg(STM32_OTGFS_DCFG);
+ regval &= ~OTGFS_DCFG_DAD_MASK;
+ regval |= ((uint32_t)address << OTGFS_DCFG_DAD_SHIFT);
+ stm32_putreg(regval, STM32_OTGFS_DCFG);
+
+ /* Are we now addressed? (i.e., do we have a non-NULL device
+ * address?)
+ */
+
+ if (address != 0)
+ {
+ priv->devstate = DEVSTATE_ADDRESSED;
+ priv->addressed = true;
+ }
+ else
+ {
+ priv->devstate = DEVSTATE_DEFAULT;
+ priv->addressed = false;
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_txfifo_flush
+ *
+ * Description:
+ * Flush the specific TX fifo.
+ *
+ *******************************************************************************/
+
+static int stm32_txfifo_flush(uint32_t txfnum)
+{
+ uint32_t regval;
+ uint32_t timeout;
+
+ /* Initiate the TX FIFO flush operation */
+
+ regval = OTGFS_GRSTCTL_TXFFLSH | txfnum;
+ stm32_putreg(regval, STM32_OTGFS_GRSTCTL);
+
+ /* Wait for the FLUSH to complete */
+
+ for (timeout = 0; timeout < STM32_FLUSH_DELAY; timeout++)
+ {
+ regval = stm32_getreg(STM32_OTGFS_GRSTCTL);
+ if ((regval & OTGFS_GRSTCTL_TXFFLSH) == 0)
+ {
+ break;
+ }
+ }
+
+ /* Wait for 3 PHY Clocks */
+
+ up_udelay(3);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_rxfifo_flush
+ *
+ * Description:
+ * Flush the RX fifo.
+ *
+ *******************************************************************************/
+
+static int stm32_rxfifo_flush(void)
+{
+ uint32_t regval;
+ uint32_t timeout;
+
+ /* Initiate the RX FIFO flush operation */
+
+ stm32_putreg(OTGFS_GRSTCTL_RXFFLSH, STM32_OTGFS_GRSTCTL);
+
+ /* Wait for the FLUSH to complete */
+
+ for (timeout = 0; timeout < STM32_FLUSH_DELAY; timeout++)
+ {
+ regval = stm32_getreg(STM32_OTGFS_GRSTCTL);
+ if ((regval & OTGFS_GRSTCTL_RXFFLSH) == 0)
+ {
+ break;
+ }
+ }
+
+ /* Wait for 3 PHY Clocks */
+
+ up_udelay(3);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_swinitialize
+ *
+ * Description:
+ * Initialize all driver data structures.
+ *
+ *******************************************************************************/
+
+static void stm32_swinitialize(FAR struct stm32_usbdev_s *priv)
+{
+ FAR struct stm32_ep_s *privep;
+ int i;
+
+ /* Initialize the device state structure */
+
+ memset(priv, 0, sizeof(struct stm32_usbdev_s));
+
+ priv->usbdev.ops = &g_devops;
+ priv->usbdev.ep0 = &priv->epin[EP0].ep;
+ priv->epavail = STM32_EP_AVAILABLE;
+
+ priv->epin[EP0].ep.priv = priv;
+ priv->epout[EP0].ep.priv = priv;
+
+ /* Initialize the endpoint lists */
+
+ for (i = 0; i < STM32_NENDPOINTS; i++)
+ {
+ /* Set endpoint operations, reference to driver structure (not
+ * really necessary because there is only one controller), and
+ * the physical endpoint number (which is just the index to the
+ * endpoint).
+ */
+
+ privep = &priv->epin[i];
+ privep->ep.ops = &g_epops;
+ privep->dev = priv;
+ privep->isin = 1;
+
+ /* The index, i, is the physical endpoint address; Map this
+ * to a logical endpoint address usable by the class driver.
+ */
+
+ privep->epphy = i;
+ privep->ep.eplog = STM32_EPPHYIN2LOG(i);
+
+ /* Control until endpoint is activated */
+
+ privep->eptype = USB_EP_ATTR_XFER_CONTROL;
+ privep->ep.maxpacket = CONFIG_USBDEV_EP0_MAXSIZE;
+ }
+
+ /* Initialize the endpoint lists */
+
+ for (i = 0; i < STM32_NENDPOINTS; i++)
+ {
+ /* Set endpoint operations, reference to driver structure (not
+ * really necessary because there is only one controller), and
+ * the physical endpoint number (which is just the index to the
+ * endpoint).
+ */
+
+ privep = &priv->epout[i];
+ privep->ep.ops = &g_epops;
+ privep->dev = priv;
+
+ /* The index, i, is the physical endpoint address; Map this
+ * to a logical endpoint address usable by the class driver.
+ */
+
+ privep->epphy = i;
+ privep->ep.eplog = STM32_EPPHYOUT2LOG(i);
+
+ /* Control until endpoint is activated */
+
+ privep->eptype = USB_EP_ATTR_XFER_CONTROL;
+ privep->ep.maxpacket = CONFIG_USBDEV_EP0_MAXSIZE;
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_hwinitialize
+ *
+ * Description:
+ * Configure the OTG FS core for operation.
+ *
+ *******************************************************************************/
+
+static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv)
+{
+ uint32_t regval;
+ uint32_t timeout;
+ uint32_t address;
+ int i;
+
+ /* At startup the core is in FS mode. */
+
+ /* Disable the USB global interrupt by clearing GINTMSK in the global OTG
+ * FS AHB configuration register.
+ */
+
+ stm32_putreg(OTGFS_GAHBCFG_TXFELVL, STM32_OTGFS_GAHBCFG);
+
+ /* Common USB OTG core initialization */
+ /* Reset after a PHY select and set Host mode. First, wait for AHB master
+ * IDLE state.
+ */
+
+ for (timeout = 0; timeout < STM32_READY_DELAY; timeout++)
+ {
+ up_udelay(3);
+ regval = stm32_getreg(STM32_OTGFS_GRSTCTL);
+ if ((regval & OTGFS_GRSTCTL_AHBIDL) != 0)
+ {
+ break;
+ }
+ }
+
+ /* Then perform the core soft reset. */
+
+ stm32_putreg(OTGFS_GRSTCTL_CSRST, STM32_OTGFS_GRSTCTL);
+ for (timeout = 0; timeout < STM32_READY_DELAY; timeout++)
+ {
+ regval = stm32_getreg(STM32_OTGFS_GRSTCTL);
+ if ((regval & OTGFS_GRSTCTL_CSRST) == 0)
+ {
+ break;
+ }
+ }
+
+ /* Wait for 3 PHY Clocks */
+
+ up_udelay(3);
+
+ /* Deactivate the power down */
+
+ regval = (OTGFS_GCCFG_PWRDWN | OTGFS_GCCFG_VBUSASEN | OTGFS_GCCFG_VBUSBSEN);
+#ifndef CONFIG_USBDEV_VBUSSENSING
+ regval |= OTGFS_GCCFG_NOVBUSSENS;
+#endif
+#ifdef CONFIG_USBDEV_SOFOUTPUT
+ regval |= OTGFS_GCCFG_SOFOUTEN;
+#endif
+ stm32_putreg(regval, STM32_OTGFS_GCCFG);
+ up_mdelay(20);
+
+ /* Force Device Mode */
+
+ regval = stm32_getreg(STM32_OTGFS_GUSBCFG);
+ regval &= ~OTGFS_GUSBCFG_FHMOD;
+ regval |= OTGFS_GUSBCFG_FDMOD;
+ stm32_putreg(regval, STM32_OTGFS_GUSBCFG);
+ up_mdelay(50);
+
+ /* Initialize device mode */
+ /* Restart the Phy Clock */
+
+ stm32_putreg(0, STM32_OTGFS_PCGCCTL);
+
+ /* Device configuration register */
+
+ regval = stm32_getreg(STM32_OTGFS_DCFG);
+ regval &= ~OTGFS_DCFG_PFIVL_MASK;
+ regval |= OTGFS_DCFG_PFIVL_80PCT;
+ stm32_putreg(regval, STM32_OTGFS_DCFG);
+
+ /* Set full speed phy */
+
+ regval = stm32_getreg(STM32_OTGFS_DCFG);
+ regval &= ~OTGFS_DCFG_DSPD_MASK;
+ regval |= OTGFS_DCFG_DSPD_FS;
+ stm32_putreg(regval, STM32_OTGFS_DCFG);
+
+ /* Set Rx FIFO size */
+
+ stm32_putreg(STM32_RXFIFO_WORDS, STM32_OTGFS_GRXFSIZ);
+
+ /* EP0 TX */
+
+ address = STM32_RXFIFO_WORDS;
+ regval = (address << OTGFS_DIEPTXF0_TX0FD_SHIFT) |
+ (STM32_EP0_TXFIFO_WORDS << OTGFS_DIEPTXF0_TX0FSA_SHIFT);
+ stm32_putreg(regval, STM32_OTGFS_DIEPTXF0);
+
+ /* EP1 TX */
+
+ address += STM32_EP0_TXFIFO_WORDS;
+ regval = (address << OTGFS_DIEPTXF_INEPTXSA_SHIFT) |
+ (STM32_EP1_TXFIFO_WORDS << OTGFS_DIEPTXF_INEPTXFD_SHIFT);
+ stm32_putreg(regval, STM32_OTGFS_DIEPTXF1);
+
+ /* EP2 TX */
+
+ address += STM32_EP1_TXFIFO_WORDS;
+ regval = (address << OTGFS_DIEPTXF_INEPTXSA_SHIFT) |
+ (STM32_EP2_TXFIFO_WORDS << OTGFS_DIEPTXF_INEPTXFD_SHIFT);
+ stm32_putreg(regval, STM32_OTGFS_DIEPTXF2);
+
+ /* EP3 TX */
+
+ address += STM32_EP2_TXFIFO_WORDS;
+ regval = (address << OTGFS_DIEPTXF_INEPTXSA_SHIFT) |
+ (STM32_EP3_TXFIFO_WORDS << OTGFS_DIEPTXF_INEPTXFD_SHIFT);
+ stm32_putreg(regval, STM32_OTGFS_DIEPTXF3);
+
+ /* Flush the FIFOs */
+
+ stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_DALL);
+ stm32_rxfifo_flush();
+
+ /* Clear all pending Device Interrupts */
+
+ stm32_putreg(0, STM32_OTGFS_DIEPMSK);
+ stm32_putreg(0, STM32_OTGFS_DOEPMSK);
+ stm32_putreg(0xffffffff, STM32_OTGFS_DAINT);
+ stm32_putreg(0, STM32_OTGFS_DAINTMSK);
+
+ /* Configure all IN endpoints */
+
+ for (i = 0; i < STM32_NENDPOINTS; i++)
+ {
+ regval = stm32_getreg(STM32_OTGFS_DIEPCTL(i));
+ if ((regval & OTGFS_DIEPCTL_EPENA) != 0)
+ {
+ /* The endpoint is already enabled */
+
+ regval = OTGFS_DIEPCTL_EPENA | OTGFS_DIEPCTL_SNAK;
+ }
+ else
+ {
+ regval = 0;
+ }
+
+ stm32_putreg(regval, STM32_OTGFS_DIEPCTL(i));
+ stm32_putreg(0, STM32_OTGFS_DIEPTSIZ(i));
+ stm32_putreg(0xff, STM32_OTGFS_DIEPINT(i));
+ }
+
+ /* Configure all OUT endpoints */
+
+ for (i = 0; i < STM32_NENDPOINTS; i++)
+ {
+ regval = stm32_getreg(STM32_OTGFS_DOEPCTL(i));
+ if ((regval & OTGFS_DOEPCTL_EPENA) != 0)
+ {
+ /* The endpoint is already enabled */
+
+ regval = OTGFS_DOEPCTL_EPENA | OTGFS_DOEPCTL_SNAK;
+ }
+ else
+ {
+ regval = 0;
+ }
+
+ stm32_putreg(regval, STM32_OTGFS_DOEPCTL(i));
+ stm32_putreg(0, STM32_OTGFS_DOEPTSIZ(i));
+ stm32_putreg(0xff, STM32_OTGFS_DOEPINT(i));
+ }
+
+ /* Disable all interrupts. */
+
+ stm32_putreg(0, STM32_OTGFS_GINTMSK);
+
+ /* Clear any pending USB_OTG Interrupts */
+
+ stm32_putreg(0xffffffff, STM32_OTGFS_GOTGINT);
+
+ /* Clear any pending interrupts */
+
+ stm32_putreg(0xbfffffff, STM32_OTGFS_GINTSTS);
+
+ /* Enable the interrupts in the INTMSK */
+
+ regval = (OTGFS_GINT_RXFLVL | OTGFS_GINT_USBSUSP | OTGFS_GINT_ENUMDNE |
+ OTGFS_GINT_IEP | OTGFS_GINT_OEP | OTGFS_GINT_USBRST);
+
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+ regval |= (OTGFS_GINT_IISOIXFR | OTGFS_GINT_IISOOXFR);
+#endif
+
+#ifdef CONFIG_USBDEV_SOFINTERRUPT
+ regval |= OTGFS_GINT_SOF;
+#endif
+
+#ifdef CONFIG_USBDEV_VBUSSENSING
+ regval |= (OTGFS_GINT_OTG | OTGFS_GINT_SRQ);
+#endif
+
+#ifdef CONFIG_DEBUG_USB
+ regval |= OTGFS_GINT_MMIS;
+#endif
+
+ stm32_putreg(regval, STM32_OTGFS_GINTMSK);
+
+ /* Enable the USB global interrupt by setting GINTMSK in the global OTG
+ * FS AHB configuration register.
+ */
+
+ stm32_putreg(OTGFS_GAHBCFG_GINTMSK | OTGFS_GAHBCFG_TXFELVL, STM32_OTGFS_GAHBCFG);
+}
+
+/*******************************************************************************
+ * Public Functions
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: up_usbinitialize
+ *
+ * Description:
+ * Initialize USB hardware.
+ *
+ * Assumptions:
+ * - This function is called very early in the initialization sequence
+ * - PLL and GIO pin initialization is not performed here but should been in
+ * the low-level boot logic: PLL1 must be configured for operation at 48MHz
+ * and P0.23 and PO.31 in PINSEL1 must be configured for Vbus and USB connect
+ * LED.
+ *
+ *******************************************************************************/
+
+void up_usbinitialize(void)
+{
+ /* At present, there is only a single OTG FS device support. Hence it is
+ * pre-allocated as g_otgfsdev. However, in most code, the private data
+ * structure will be referenced using the 'priv' pointer (rather than the
+ * global data) in order to simplify any future support for multiple devices.
+ */
+
+ FAR struct stm32_usbdev_s *priv = &g_otgfsdev;
+ int ret;
+
+ usbtrace(TRACE_DEVINIT, 0);
+
+ /* Here we assume that:
+ *
+ * 1. GPIOA and OTG FS peripheral clocking has already been enabled as part
+ * of the boot sequence.
+ * 2. Board-specific logic has already enabled other board specific GPIOs
+ * for things like soft pull-up, VBUS sensing, power controls, and over-
+ * current detection.
+ */
+
+ /* Configure OTG FS alternate function pins */
+
+ stm32_configgpio(GPIO_OTGFS_DM);
+ stm32_configgpio(GPIO_OTGFS_DP);
+ stm32_configgpio(GPIO_OTGFS_ID);
+ stm32_configgpio(GPIO_OTGFS_SOF);
+
+ /* Uninitialize the hardware so that we know that we are starting from a
+ * known state. */
+
+ up_usbuninitialize();
+
+ /* Initialie the driver data structure */
+
+ stm32_swinitialize(priv);
+
+ /* Attach the OTG FS interrupt handler */
+
+ ret = irq_attach(STM32_IRQ_OTGFS, stm32_usbinterrupt);
+ if (ret < 0)
+ {
+ udbg("irq_attach failed\n", ret);
+ goto errout;
+ }
+
+ /* Initialize the USB OTG core */
+
+ stm32_hwinitialize(priv);
+
+ /* Disconnect device */
+
+ stm32_pullup(&priv->usbdev, false);
+
+ /* Reset/Re-initialize the USB hardware */
+
+ stm32_usbreset(priv);
+
+ /* Enable USB controller interrupts at the NVIC */
+
+ up_enable_irq(STM32_IRQ_OTGFS);
+
+ /* Set the interrrupt priority */
+
+ up_prioritize_irq(STM32_IRQ_OTGFS, CONFIG_OTGFS_PRI);
+ return;
+
+errout:
+ up_usbuninitialize();
+}
+
+/*******************************************************************************
+ * Name: up_usbuninitialize
+ *******************************************************************************/
+
+void up_usbuninitialize(void)
+{
+ /* At present, there is only a single OTG FS device support. Hence it is
+ * pre-allocated as g_otgfsdev. However, in most code, the private data
+ * structure will be referenced using the 'priv' pointer (rather than the
+ * global data) in order to simplify any future support for multiple devices.
+ */
+
+ FAR struct stm32_usbdev_s *priv = &g_otgfsdev;
+ irqstate_t flags;
+ int i;
+
+ usbtrace(TRACE_DEVUNINIT, 0);
+
+ if (priv->driver)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DRIVERREGISTERED), 0);
+ usbdev_unregister(priv->driver);
+ }
+
+ /* Disconnect device */
+
+ flags = irqsave();
+ stm32_pullup(&priv->usbdev, false);
+ priv->usbdev.speed = USB_SPEED_UNKNOWN;
+
+ /* Disable and detach IRQs */
+
+ up_disable_irq(STM32_IRQ_OTGFS);
+ irq_detach(STM32_IRQ_OTGFS);
+
+ /* Disable all endpoint interrupts */
+
+ for (i = 0; i < STM32_NENDPOINTS; i++)
+ {
+ stm32_putreg(0xff, STM32_OTGFS_DIEPINT(i));
+ stm32_putreg(0xff, STM32_OTGFS_DOEPINT(i));
+ }
+
+ stm32_putreg(0, STM32_OTGFS_DIEPMSK);
+ stm32_putreg(0, STM32_OTGFS_DOEPMSK);
+ stm32_putreg(0, STM32_OTGFS_DAINTMSK);
+ stm32_putreg(0xffffffff, STM32_OTGFS_DAINT);
+
+ /* Flush the FIFOs */
+
+ stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_DALL);
+ stm32_rxfifo_flush();
+
+ /* TODO: Turn off USB power and clocking */
+
+ priv->devstate = DEVSTATE_DEFAULT;
+ irqrestore(flags);
+}
+
+/*******************************************************************************
+ * Name: usbdev_register
+ *
+ * Description:
+ * Register a USB device class driver. The class driver's bind() method will be
+ * called to bind it to a USB device driver.
+ *
+ *******************************************************************************/
+
+int usbdev_register(struct usbdevclass_driver_s *driver)
+{
+ /* At present, there is only a single OTG FS device support. Hence it is
+ * pre-allocated as g_otgfsdev. However, in most code, the private data
+ * structure will be referenced using the 'priv' pointer (rather than the
+ * global data) in order to simplify any future support for multiple devices.
+ */
+
+ FAR struct stm32_usbdev_s *priv = &g_otgfsdev;
+ int ret;
+
+ usbtrace(TRACE_DEVREGISTER, 0);
+
+#ifdef CONFIG_DEBUG
+ if (!driver || !driver->ops->bind || !driver->ops->unbind ||
+ !driver->ops->disconnect || !driver->ops->setup)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+
+ if (priv->driver)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DRIVER), 0);
+ return -EBUSY;
+ }
+#endif
+
+ /* First hook up the driver */
+
+ priv->driver = driver;
+
+ /* Then bind the class driver */
+
+ ret = CLASS_BIND(driver, &priv->usbdev);
+ if (ret)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BINDFAILED), (uint16_t)-ret);
+ priv->driver = NULL;
+ }
+ else
+ {
+ /* Enable USB controller interrupts */
+
+ up_enable_irq(STM32_IRQ_OTGFS);
+
+ /* FIXME: nothing seems to call DEV_CONNECT(), but we need to set
+ * the RS bit to enable the controller. It kind of makes sense
+ * to do this after the class has bound to us...
+ * GEN: This bug is really in the class driver. It should make the
+ * soft connect when it is ready to be enumerated. I have added
+ * that logic to the class drivers but left this logic here.
+ */
+
+ stm32_pullup(&priv->usbdev, true);
+ priv->usbdev.speed = USB_SPEED_FULL;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: usbdev_unregister
+ *
+ * Description:
+ * Un-register usbdev class driver.If the USB device is connected to a USB host,
+ * it will first disconnect(). The driver is also requested to unbind() and clean
+ * up any device state, before this procedure finally returns.
+ *
+ *******************************************************************************/
+
+int usbdev_unregister(struct usbdevclass_driver_s *driver)
+{
+ /* At present, there is only a single OTG FS device support. Hence it is
+ * pre-allocated as g_otgfsdev. However, in most code, the private data
+ * structure will be referenced using the 'priv' pointer (rather than the
+ * global data) in order to simplify any future support for multiple devices.
+ */
+
+ FAR struct stm32_usbdev_s *priv = &g_otgfsdev;
+ irqstate_t flags;
+
+ usbtrace(TRACE_DEVUNREGISTER, 0);
+
+#ifdef CONFIG_DEBUG
+ if (driver != priv->driver)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+
+ /* Reset the hardware and cancel all requests. All requests must be
+ * canceled while the class driver is still bound.
+ */
+
+ flags = irqsave();
+ stm32_usbreset(priv);
+
+ /* Unbind the class driver */
+
+ CLASS_UNBIND(driver, &priv->usbdev);
+
+ /* Disable USB controller interrupts */
+
+ up_disable_irq(STM32_IRQ_OTGFS);
+
+ /* Disconnect device */
+
+ stm32_pullup(&priv->usbdev, false);
+
+ /* Unhook the driver */
+
+ priv->driver = NULL;
+ irqrestore(flags);
+
+ return OK;
+}
+
+#endif /* CONFIG_USBDEV && CONFIG_STM32_OTGFSDEV */
diff --git a/nuttx/arch/arm/src/stm32/stm32_pm.h b/nuttx/arch/arm/src/stm32/stm32_pm.h
new file mode 100644
index 000000000..be040d296
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_pm.h
@@ -0,0 +1,142 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_pm.h
+ *
+ * Copyright (C) 2012 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_STM32_STM32_PM_H
+#define __ARCH_ARM_SRC_STM32_STM32_PM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+
+#include "chip.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+ #ifndef __ASSEMBLY__
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_pmstop
+ *
+ * Description:
+ * Enter STOP mode.
+ *
+ * Input Parameters:
+ * lpds - true: To further reduce power consumption in Stop mode, put the
+ * internal voltage regulator in low-power mode using the LPDS bit
+ * of the Power control register (PWR_CR).
+ *
+ * Returned Value:
+ * Zero means that the STOP was successfully entered and the system has
+ * been re-awakened. The internal volatage regulator is back to its
+ * original state. Otherwise, STOP mode did not occur and a negated
+ * errno value is returned to indicate the cause of the failure.
+ *
+ ****************************************************************************/
+
+EXTERN int stm32_pmstop(bool lpds);
+
+/****************************************************************************
+ * Name: stm32_pmstandby
+ *
+ * Description:
+ * Enter STANDBY mode.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value.
+ * On success, this function will not return (STANDBY mode can only be
+ * terminated with a reset event). Otherwise, STANDBY mode did not occur
+ * and a negated errno value is returned to indicate the cause of the
+ * failure.
+ *
+ ****************************************************************************/
+
+EXTERN int stm32_pmstandby(void);
+
+/****************************************************************************
+ * Name: stm32_pmsleep
+ *
+ * Description:
+ * Enter SLEEP mode.
+ *
+ * Input Parameters:
+ * sleeponexit - true: SLEEPONEXIT bit is set when the WFI instruction is
+ * executed, the MCU enters Sleep mode as soon as it
+ * exits the lowest priority ISR.
+ * - false: SLEEPONEXIT bit is cleared, the MCU enters Sleep mode
+ * as soon as WFI or WFE instruction is executed.
+ * Returned Value:
+ * Zero means that the STOP was successfully entered and the system has
+ * been re-awakened. The internal volatage regulator is back to its
+ * original state. Otherwise, STOP mode did not occur and a negated
+ * errno value is returned to indicate the cause of the failure.
+ *
+ ****************************************************************************/
+
+EXTERN void stm32_pmsleep(bool sleeponexit);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM_SRC_STM32_STM32_PM_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_pminitialize.c b/nuttx/arch/arm/src/stm32/stm32_pminitialize.c
new file mode 100644
index 000000000..a1f44a7f4
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_pminitialize.c
@@ -0,0 +1,94 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_pminitialize.c
+ *
+ * Copyright (C) 2012 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 <nuttx/power/pm.h>
+
+#include "up_internal.h"
+#include "stm32_pm.h"
+
+#ifdef CONFIG_PM
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_pminitialize
+ *
+ * Description:
+ * This function is called by MCU-specific logic at power-on reset in
+ * order to provide one-time initialization the power management subystem.
+ * This function must be called *very* early in the intialization sequence
+ * *before* any other device drivers are initialized (since they may
+ * attempt to register with the power management subsystem).
+ *
+ * Input parameters:
+ * None.
+ *
+ * Returned value:
+ * None.
+ *
+ ****************************************************************************/
+
+void up_pminitialize(void)
+{
+ /* Then initialize the NuttX power management subsystem proper */
+
+ pm_initialize();
+}
+
+#endif /* CONFIG_PM */
diff --git a/nuttx/arch/arm/src/stm32/stm32_pmsleep.c b/nuttx/arch/arm/src/stm32/stm32_pmsleep.c
new file mode 100644
index 000000000..3027b99a7
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_pmsleep.c
@@ -0,0 +1,117 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_pmsleep.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Authors: Gregory Nutt <gnutt@nuttx.org>
+ * Diego Sanchez <dsanchez@nx-engineering.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+
+#include "up_arch.h"
+#include "nvic.h"
+#include "stm32_pwr.h"
+#include "stm32_pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_pmsleep
+ *
+ * Description:
+ * Enter SLEEP mode.
+ *
+ * Input Parameters:
+ * sleeponexit - true: SLEEPONEXIT bit is set when the WFI instruction is
+ * executed, the MCU enters Sleep mode as soon as it
+ * exits the lowest priority ISR.
+ * - false: SLEEPONEXIT bit is cleared, the MCU enters Sleep mode
+ * as soon as WFI or WFE instruction is executed.
+ * Returned Value:
+ * Zero means that the STOP was successfully entered and the system has
+ * been re-awakened. The internal volatage regulator is back to its
+ * original state. Otherwise, STOP mode did not occur and a negated
+ * errno value is returned to indicate the cause of the failure.
+ *
+ ****************************************************************************/
+
+void stm32_pmsleep(bool sleeponexit)
+{
+ uint32_t regval;
+
+ /* Clear SLEEPDEEP bit of Cortex System Control Register */
+
+ regval = getreg32(NVIC_SYSCON);
+ regval &= ~NVIC_SYSCON_SLEEPDEEP;
+ if (sleeponexit)
+ {
+ regval |= NVIC_SYSCON_SLEEPONEXIT;
+ }
+ else
+ {
+ regval &= ~NVIC_SYSCON_SLEEPONEXIT;
+ }
+
+ putreg32(regval, NVIC_SYSCON);
+
+ /* Sleep until the wakeup interrupt or event occurs */
+
+#ifdef CONFIG_PM_WFE
+ /* Mode: SLEEP + Entry with WFE */
+
+ asm("wfe");
+#else
+ /* Mode: SLEEP + Entry with WFI */
+
+ asm("wfi");
+#endif
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_pmstandby.c b/nuttx/arch/arm/src/stm32/stm32_pmstandby.c
new file mode 100644
index 000000000..467edaec2
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_pmstandby.c
@@ -0,0 +1,109 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_pmstandby.c
+ *
+ * Copyright (C) 2012 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 <stdbool.h>
+
+#include "up_arch.h"
+#include "nvic.h"
+#include "stm32_pwr.h"
+#include "stm32_pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_pmstandby
+ *
+ * Description:
+ * Enter STANDBY mode.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value.
+ * On success, this function will not return (STANDBY mode can only be
+ * terminated with a reset event). Otherwise, STANDBY mode did not occur
+ * and a negated errno value is returned to indicate the cause of the
+ * failure.
+ *
+ ****************************************************************************/
+
+int stm32_pmstandby(void)
+{
+ uint32_t regval;
+
+ /* Clear the Wake-Up Flag by setting the CWUF bit in the power control
+ * register.
+ */
+
+ regval = getreg32(STM32_PWR_CR);
+ regval |= PWR_CR_CWUF;
+ putreg32(regval, STM32_PWR_CR);
+
+ /* Set the Power Down Deep Sleep (PDDS) bit in the power control register. */
+
+ regval |= PWR_CR_PDDS;
+ putreg32(regval, STM32_PWR_CR);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+
+ regval = getreg32(NVIC_SYSCON);
+ regval |= NVIC_SYSCON_SLEEPDEEP;
+ putreg32(regval, NVIC_SYSCON);
+
+ /* Sleep until the wakeup reset occurs */
+
+ asm("wfi");
+ return OK; /* Won't get here */
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_pmstop.c b/nuttx/arch/arm/src/stm32/stm32_pmstop.c
new file mode 100644
index 000000000..14ce63b55
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_pmstop.c
@@ -0,0 +1,122 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_pmstop.c
+ *
+ * Copyright (C) 2012 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 <stdbool.h>
+
+#include "up_arch.h"
+#include "nvic.h"
+#include "stm32_pwr.h"
+#include "stm32_pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_pmstop
+ *
+ * Description:
+ * Enter STOP mode.
+ *
+ * Input Parameters:
+ * lpds - true: To further reduce power consumption in Stop mode, put the
+ * internal voltage regulator in low-power mode using the LPDS bit
+ * of the Power control register (PWR_CR).
+ *
+ * Returned Value:
+ * Zero means that the STOP was successfully entered and the system has
+ * been re-awakened. The internal volatage regulator is back to its
+ * original state. Otherwise, STOP mode did not occur and a negated
+ * errno value is returned to indicate the cause of the failure.
+ *
+ ****************************************************************************/
+
+int stm32_pmstop(bool lpds)
+{
+ uint32_t regval;
+
+ /* Clear the Power Down Deep Sleep (PDDS) and the Low Power Deep Sleep
+ * (LPDS)) bits in the power control register.
+ */
+
+ regval = getreg32(STM32_PWR_CR);
+ regval &= ~(PWR_CR_LPDS | PWR_CR_PDDS);
+
+ /* Set the Low Power Deep Sleep (LPDS) bit if so requested */
+
+ if (lpds)
+ {
+ regval |= PWR_CR_LPDS;
+ }
+
+ putreg32(regval, STM32_PWR_CR);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+
+ regval = getreg32(NVIC_SYSCON);
+ regval |= NVIC_SYSCON_SLEEPDEEP;
+ putreg32(regval, NVIC_SYSCON);
+
+ /* Sleep until the wakeup interrupt or event occurs */
+
+#ifdef CONFIG_PM_WFE
+ /* Mode: SLEEP + Entry with WFE */
+
+ asm("wfe");
+#else
+ /* Mode: SLEEP + Entry with WFI */
+
+ asm("wfi");
+#endif
+ return OK;
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_pwm.c b/nuttx/arch/arm/src/stm32/stm32_pwm.c
new file mode 100644
index 000000000..a3ef23e57
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_pwm.c
@@ -0,0 +1,1525 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_pwm.c
+ *
+ * Copyright (C) 2011-2012 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 <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/pwm.h>
+#include <arch/board/board.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "chip.h"
+#include "stm32_pwm.h"
+#include "stm32_internal.h"
+
+/* This module then only compiles if there is at least one enabled timer
+ * intended for use with the PWM upper half driver.
+ */
+
+#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM2_PWM) || \
+ defined(CONFIG_STM32_TIM3_PWM) || defined(CONFIG_STM32_TIM4_PWM) || \
+ defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM8_PWM) || \
+ defined(CONFIG_STM32_TIM9_PWM) || defined(CONFIG_STM32_TIM10_PWM) || \
+ defined(CONFIG_STM32_TIM11_PWM) || defined(CONFIG_STM32_TIM12_PWM) || \
+ defined(CONFIG_STM32_TIM13_PWM) || defined(CONFIG_STM32_TIM14_PWM)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* PWM/Timer Definitions ****************************************************/
+/* The following definitions are used to identify the various time types */
+
+#define TIMTYPE_BASIC 0 /* Basic timers: TIM6-7 */
+#define TIMTYPE_GENERAL16 1 /* General 16-bit timers: TIM2-5 on F1 */
+#define TIMTYPE_COUNTUP16 2 /* General 16-bit count-up timers: TIM9-14 on F4 */
+#define TIMTYPE_GENERAL32 3 /* General 32-bit timers: TIM2-5 on F4 */
+#define TIMTYPE_ADVANCED 4 /* Advanced timers: TIM1-8 */
+
+#define TIMTYPE_TIM1 TIMTYPE_ADVANCED
+#ifdef CONFIG_STM32_STM32F10XX
+# define TIMTYPE_TIM2 TIMTYPE_GENERAL16
+# define TIMTYPE_TIM3 TIMTYPE_GENERAL16
+# define TIMTYPE_TIM4 TIMTYPE_GENERAL16
+# define TIMTYPE_TIM5 TIMTYPE_GENERAL16
+#else
+# define TIMTYPE_TIM2 TIMTYPE_GENERAL32
+# define TIMTYPE_TIM3 TIMTYPE_GENERAL32
+# define TIMTYPE_TIM4 TIMTYPE_GENERAL32
+# define TIMTYPE_TIM5 TIMTYPE_GENERAL32
+#endif
+#define TIMTYPE_TIM6 TIMTYPE_BASIC
+#define TIMTYPE_TIM7 TIMTYPE_BASIC
+#define TIMTYPE_TIM8 TIMTYPE_ADVANCED
+#define TIMTYPE_TIM9 TIMTYPE_COUNTUP16
+#define TIMTYPE_TIM10 TIMTYPE_COUNTUP16
+#define TIMTYPE_TIM11 TIMTYPE_COUNTUP16
+#define TIMTYPE_TIM12 TIMTYPE_COUNTUP16
+#define TIMTYPE_TIM13 TIMTYPE_COUNTUP16
+#define TIMTYPE_TIM14 TIMTYPE_COUNTUP16
+
+/* Debug ********************************************************************/
+/* Non-standard debug that may be enabled just for testing PWM */
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_DEBUG_PWM
+#endif
+
+#ifdef CONFIG_DEBUG_PWM
+# define pwmdbg dbg
+# define pwmlldbg lldbg
+# ifdef CONFIG_DEBUG_VERBOSE
+# define pwmvdbg vdbg
+# define pwmllvdbg llvdbg
+# define pwm_dumpgpio(p,m) stm32_dumpgpio(p,m)
+# else
+# define pwmlldbg(x...)
+# define pwmllvdbg(x...)
+# define pwm_dumpgpio(p,m)
+# endif
+#else
+# define pwmdbg(x...)
+# define pwmlldbg(x...)
+# define pwmvdbg(x...)
+# define pwmllvdbg(x...)
+# define pwm_dumpgpio(p,m)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+/* This structure representst the state of one PWM timer */
+
+struct stm32_pwmtimer_s
+{
+ FAR const struct pwm_ops_s *ops; /* PWM operations */
+ uint8_t timid; /* Timer ID {1,...,14} */
+ uint8_t channel; /* Timer output channel: {1,..4} */
+ uint8_t timtype; /* See the TIMTYPE_* definitions */
+#ifdef CONFIG_PWM_PULSECOUNT
+ uint8_t irq; /* Timer update IRQ */
+ uint8_t prev; /* The previous value of the RCR (pre-loaded) */
+ uint8_t curr; /* The current value of the RCR (pre-loaded) */
+ uint32_t count; /* Remaining pluse count */
+#endif
+ uint32_t base; /* The base address of the timer */
+ uint32_t pincfg; /* Output pin configuration */
+ uint32_t pclk; /* The frequency of the peripheral clock
+ * that drives the timer module. */
+#ifdef CONFIG_PWM_PULSECOUNT
+ FAR void * handle; /* Handle used for upper-half callback */
+#endif
+};
+
+/****************************************************************************
+ * Static Function Prototypes
+ ****************************************************************************/
+/* Register access */
+
+static uint16_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset);
+static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset, uint16_t value);
+
+#if defined(CONFIG_DEBUG_PWM) && defined(CONFIG_DEBUG_VERBOSE)
+static void pwm_dumpregs(struct stm32_pwmtimer_s *priv, FAR const char *msg);
+#else
+# define pwm_dumpregs(priv,msg)
+#endif
+
+/* Timer management */
+
+static int pwm_timer(FAR struct stm32_pwmtimer_s *priv,
+ FAR const struct pwm_info_s *info);
+
+#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM))
+static int pwm_interrupt(struct stm32_pwmtimer_s *priv);
+#if defined(CONFIG_STM32_TIM1_PWM)
+static int pwm_tim1interrupt(int irq, void *context);
+#endif
+#if defined(CONFIG_STM32_TIM8_PWM)
+static int pwm_tim8interrupt(int irq, void *context);
+#endif
+static uint8_t pwm_pulsecount(uint32_t count);
+#endif
+
+/* PWM driver methods */
+
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
+
+#ifdef CONFIG_PWM_PULSECOUNT
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+ FAR const struct pwm_info_s *info,
+ FAR void *handle);
+#else
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+ FAR const struct pwm_info_s *info);
+#endif
+
+static int pwm_stop(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev,
+ int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+/* This is the list of lower half PWM driver methods used by the upper half driver */
+
+static const struct pwm_ops_s g_pwmops =
+{
+ .setup = pwm_setup,
+ .shutdown = pwm_shutdown,
+ .start = pwm_start,
+ .stop = pwm_stop,
+ .ioctl = pwm_ioctl,
+};
+
+#ifdef CONFIG_STM32_TIM1_PWM
+static struct stm32_pwmtimer_s g_pwm1dev =
+{
+ .ops = &g_pwmops,
+ .timid = 1,
+ .channel = CONFIG_STM32_TIM1_CHANNEL,
+ .timtype = TIMTYPE_TIM1,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM1UP,
+#endif
+ .base = STM32_TIM1_BASE,
+ .pincfg = PWM_TIM1_PINCFG,
+ .pclk = STM32_APB2_TIM1_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM2_PWM
+static struct stm32_pwmtimer_s g_pwm2dev =
+{
+ .ops = &g_pwmops,
+ .timid = 2,
+ .channel = CONFIG_STM32_TIM2_CHANNEL,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM2,
+#endif
+ .timtype = TIMTYPE_TIM2,
+ .base = STM32_TIM2_BASE,
+ .pincfg = PWM_TIM2_PINCFG,
+ .pclk = STM32_APB1_TIM2_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM3_PWM
+static struct stm32_pwmtimer_s g_pwm3dev =
+{
+ .ops = &g_pwmops,
+ .timid = 3,
+ .channel = CONFIG_STM32_TIM3_CHANNEL,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM3,
+#endif
+ .timtype = TIMTYPE_TIM3,
+ .base = STM32_TIM3_BASE,
+ .pincfg = PWM_TIM3_PINCFG,
+ .pclk = STM32_APB1_TIM3_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM4_PWM
+static struct stm32_pwmtimer_s g_pwm4dev =
+{
+ .ops = &g_pwmops,
+ .timid = 4,
+ .channel = CONFIG_STM32_TIM4_CHANNEL,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM4,
+#endif
+ .timtype = TIMTYPE_TIM4,
+ .base = STM32_TIM4_BASE,
+ .pincfg = PWM_TIM4_PINCFG,
+ .pclk = STM32_APB1_TIM4_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM5_PWM
+static struct stm32_pwmtimer_s g_pwm5dev =
+{
+ .ops = &g_pwmops,
+ .timid = 5,
+ .channel = CONFIG_STM32_TIM5_CHANNEL,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM5,
+#endif
+ .timtype = TIMTYPE_TIM5,
+ .base = STM32_TIM5_BASE,
+ .pincfg = PWM_TIM5_PINCFG,
+ .pclk = STM32_APB1_TIM5_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM8_PWM
+static struct stm32_pwmtimer_s g_pwm8dev =
+{
+ .ops = &g_pwmops,
+ .timid = 8,
+ .channel = CONFIG_STM32_TIM8_CHANNEL,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM8UP,
+#endif
+ .timtype = TIMTYPE_TIM8,
+ .base = STM32_TIM8_BASE,
+ .pincfg = PWM_TIM8_PINCFG,
+ .pclk = STM32_APB2_TIM8_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM9_PWM
+static struct stm32_pwmtimer_s g_pwm9dev =
+{
+ .ops = &g_pwmops,
+ .timid = 9,
+ .channel = CONFIG_STM32_TIM9_CHANNEL,
+ .timtype = TIMTYPE_TIM9,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM9,
+#endif
+ .base = STM32_TIM9_BASE,
+ .pincfg = PWM_TIM9_PINCFG,
+ .pclk = STM32_APB2_TIM9_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM10_PWM
+static struct stm32_pwmtimer_s g_pwm10dev =
+{
+ .ops = &g_pwmops,
+ .timid = 10,
+ .channel = CONFIG_STM32_TIM10_CHANNEL,
+ .timtype = TIMTYPE_TIM10,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM10,
+#endif
+ .base = STM32_TIM10_BASE,
+ .pincfg = PWM_TIM10_PINCFG,
+ .pclk = STM32_APB2_TIM10_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM11_PWM
+static struct stm32_pwmtimer_s g_pwm11dev =
+{
+ .ops = &g_pwmops,
+ .timid = 11,
+ .channel = CONFIG_STM32_TIM11_CHANNEL,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM11,
+#endif
+ .timtype = TIMTYPE_TIM11,
+ .base = STM32_TIM11_BASE,
+ .pincfg = PWM_TIM11_PINCFG,
+ .pclk = STM32_APB2_TIM11_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM12_PWM
+static struct stm32_pwmtimer_s g_pwm12dev =
+{
+ .ops = &g_pwmops,
+ .timid = 12,
+ .channel = CONFIG_STM32_TIM12_CHANNEL,
+ .timtype = TIMTYPE_TIM12,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM12,
+#endif
+ .base = STM32_TIM12_BASE,
+ .pincfg = PWM_TIM12_PINCFG,
+ .pclk = STM32_APB1_TIM12_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM13_PWM
+static struct stm32_pwmtimer_s g_pwm13dev =
+{
+ .ops = &g_pwmops,
+ .timid = 13,
+ .channel = CONFIG_STM32_TIM13_CHANNEL,
+ .timtype = TIMTYPE_TIM13,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM13,
+#endif
+ .base = STM32_TIM13_BASE,
+ .pincfg = PWM_TIM13_PINCFG,
+ .pclk = STM32_APB1_TIM13_CLKIN,
+};
+#endif
+
+#ifdef CONFIG_STM32_TIM14_PWM
+static struct stm32_pwmtimer_s g_pwm14dev =
+{
+ .ops = &g_pwmops,
+ .timid = 14,
+ .channel = CONFIG_STM32_TIM14_CHANNEL,
+ .timtype = TIMTYPE_TIM14,
+#ifdef CONFIG_PWM_PULSECOUNT
+ .irq = STM32_IRQ_TIM14,
+#endif
+ .base = STM32_TIM14_BASE,
+ .pincfg = PWM_TIM14_PINCFG,
+ .pclk = STM32_APB1_TIM14_CLKIN,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwm_getreg
+ *
+ * Description:
+ * Read the value of an PWM timer register.
+ *
+ * Input Parameters:
+ * priv - A reference to the PWM block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * The current contents of the specified register
+ *
+ ****************************************************************************/
+
+static uint16_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset)
+{
+ return getreg16(priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: pwm_putreg
+ *
+ * Description:
+ * Read the value of an PWM timer register.
+ *
+ * Input Parameters:
+ * priv - A reference to the PWM block status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset, uint16_t value)
+{
+ putreg16(value, priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: pwm_dumpregs
+ *
+ * Description:
+ * Dump all timer registers.
+ *
+ * Input parameters:
+ * priv - A reference to the PWM block status
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_DEBUG_PWM) && defined(CONFIG_DEBUG_VERBOSE)
+static void pwm_dumpregs(struct stm32_pwmtimer_s *priv, FAR const char *msg)
+{
+ pwmvdbg("%s:\n", msg);
+ pwmvdbg(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n",
+ pwm_getreg(priv, STM32_GTIM_CR1_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_CR2_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_SMCR_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_DIER_OFFSET));
+ pwmvdbg(" SR: %04x EGR: %04x CCMR1: %04x CCMR2: %04x\n",
+ pwm_getreg(priv, STM32_GTIM_SR_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_EGR_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_CCMR2_OFFSET));
+ pwmvdbg(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n",
+ pwm_getreg(priv, STM32_GTIM_CCER_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_CNT_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_PSC_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_ARR_OFFSET));
+ pwmvdbg(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n",
+ pwm_getreg(priv, STM32_GTIM_CCR1_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_CCR2_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_CCR3_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_CCR4_OFFSET));
+#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM)
+ if (priv->timtype == TIMTYPE_ADVANCED)
+ {
+ pwmvdbg(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n",
+ pwm_getreg(priv, STM32_ATIM_RCR_OFFSET),
+ pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET),
+ pwm_getreg(priv, STM32_ATIM_DCR_OFFSET),
+ pwm_getreg(priv, STM32_ATIM_DMAR_OFFSET));
+ }
+ else
+#endif
+ {
+ pwmvdbg(" DCR: %04x DMAR: %04x\n",
+ pwm_getreg(priv, STM32_GTIM_DCR_OFFSET),
+ pwm_getreg(priv, STM32_GTIM_DMAR_OFFSET));
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: pwm_timer
+ *
+ * Description:
+ * (Re-)initialize the timer resources and start the pulsed output
+ *
+ * Input parameters:
+ * priv - 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 pwm_timer(FAR struct stm32_pwmtimer_s *priv,
+ FAR const struct pwm_info_s *info)
+{
+ /* Calculated values */
+
+ uint32_t prescaler;
+ uint32_t timclk;
+ uint32_t reload;
+ uint32_t ccr;
+
+ /* Register contents */
+
+ uint16_t cr1;
+ uint16_t ccer;
+ uint16_t cr2;
+ uint16_t ccmr1;
+ uint16_t ccmr2;
+
+ /* New timer regiser bit settings */
+
+ uint16_t ccenable;
+ uint16_t ocmode1;
+ uint16_t ocmode2;
+
+ DEBUGASSERT(priv != NULL && info != NULL);
+
+#ifdef CONFIG_PWM_PULSECOUNT
+ pwmvdbg("TIM%d channel: %d frequency: %d duty: %08x count: %d\n",
+ priv->timid, priv->channel, info->frequency,
+ info->duty, info->count);
+#else
+ pwmvdbg("TIM%d channel: %d frequency: %d duty: %08x\n",
+ priv->timid, priv->channel, info->frequency, info->duty);
+#endif
+ DEBUGASSERT(info->frequency > 0 && info->duty > 0 &&
+ info->duty < uitoub16(100));
+
+ /* Disable all interrupts and DMA requests, clear all pending status */
+
+#ifdef CONFIG_PWM_PULSECOUNT
+ pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, 0);
+ pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
+#endif
+
+ /* Calculate optimal values for the timer prescaler and for the timer reload
+ * register. If' frequency' is the desired frequency, then
+ *
+ * reload = timclk / frequency
+ * timclk = pclk / presc
+ *
+ * Or,
+ *
+ * reload = pclk / presc / frequency
+ *
+ * There are many solutions to this this, but the best solution will be the
+ * one that has the largest reload value and the smallest prescaler value.
+ * That is the solution that should give us the most accuracy in the timer
+ * control. Subject to:
+ *
+ * 0 <= presc <= 65536
+ * 1 <= reload <= 65535
+ *
+ * So presc = pclk / 65535 / frequency would be optimal.
+ *
+ * Example:
+ *
+ * pclk = 42 MHz
+ * frequency = 100 Hz
+ *
+ * prescaler = 42,000,000 / 65,535 / 100
+ * = 6.4 (or 7 -- taking the ceiling always)
+ * timclk = 42,000,000 / 7
+ * = 6,000,000
+ * reload = 7,000,000 / 100
+ * = 60,000
+ */
+
+ prescaler = (priv->pclk / info->frequency + 65534) / 65535;
+ if (prescaler < 1)
+ {
+ prescaler = 1;
+ }
+ else if (prescaler > 65536)
+ {
+ prescaler = 65536;
+ }
+
+ timclk = priv->pclk / prescaler;
+
+ reload = timclk / info->frequency;
+ if (reload < 1)
+ {
+ reload = 1;
+ }
+ else if (reload > 65535)
+ {
+ reload = 65535;
+ }
+
+ /* Duty cycle:
+ *
+ * duty cycle = ccr / reload (fractional value)
+ */
+
+ ccr = b16toi(info->duty * reload + b16HALF);
+
+ pwmvdbg("TIM%d PCLK: %d frequency: %d TIMCLK: %d prescaler: %d reload: %d ccr: %d\n",
+ priv->timid, priv->pclk, info->frequency, timclk, prescaler, reload, ccr);
+
+ /* Set up the timer CR1 register:
+ *
+ * 1-8 CKD[1:0] ARPE CMS[1:0] DIR OPM URS UDIS CEN
+ * 2-5 CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN
+ * 6-7 ARPE OPM URS UDIS CEN
+ * 9-14 CKD[1:0] ARPE URS UDIS CEN
+ */
+
+ cr1 = pwm_getreg(priv, STM32_GTIM_CR1_OFFSET);
+
+ /* Disable the timer until we get it configured */
+
+ cr1 &= ~GTIM_CR1_CEN;
+
+ /* Set the counter mode for the advanced timers (1,8) and most general
+ * purpose timers (all 2-5, but not 9-14), i.e., all but TIMTYPE_COUNTUP16
+ * and TIMTYPE_BASIC
+ */
+
+#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM2_PWM) || \
+ defined(CONFIG_STM32_TIM3_PWM) || defined(CONFIG_STM32_TIM4_PWM) || \
+ defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM8_PWM)
+
+ if (priv->timtype != TIMTYPE_BASIC && priv->timtype != TIMTYPE_COUNTUP16)
+ {
+ /* Select the Counter Mode == count up:
+ *
+ * GTIM_CR1_EDGE: The counter counts up or down depending on the
+ * direction bit(DIR).
+ * GTIM_CR1_DIR: 0: count up, 1: count down
+ */
+
+ cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK);
+ cr1 |= GTIM_CR1_EDGE;
+ }
+#endif
+
+ /* Set the clock division to zero for all (but the basic timers, but there
+ * should be no basic timers in this context
+ */
+
+ cr1 &= ~GTIM_CR1_CKD_MASK;
+ pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+ /* Set the reload and prescaler values */
+
+ pwm_putreg(priv, STM32_GTIM_ARR_OFFSET, (uint16_t)reload);
+ pwm_putreg(priv, STM32_GTIM_PSC_OFFSET, (uint16_t)(prescaler - 1));
+
+ /* Set the advanced timer's repitition counter */
+
+#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM)
+ if (priv->timtype == TIMTYPE_ADVANCED)
+ {
+ /* If a non-zero repetition count has been selected, then set the
+ * repitition counter to the count-1 (pwm_start() has already
+ * assured us that the count value is within range).
+ */
+
+#ifdef CONFIG_PWM_PULSECOUNT
+ if (info->count > 0)
+ {
+ /* Save the remining count and the number of counts that will have
+ * elapsed on the first interrupt.
+ */
+
+ /* If the first interrupt occurs at the end end of the first
+ * repition count, then the count will be the same as the RCR
+ * value.
+ */
+
+ priv->prev = pwm_pulsecount(info->count);
+ pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->prev - 1);
+
+ /* Generate an update event to reload the prescaler. This should
+ * preload the RCR into active repetition counter.
+ */
+
+ pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+
+ /* Now set the value of the RCR that will be loaded on the next
+ * update event.
+ */
+
+ priv->count = info->count;
+ priv->curr = pwm_pulsecount(info->count - priv->prev);
+ pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
+ }
+
+ /* Otherwise, just clear the repitition counter */
+
+ else
+#endif
+ {
+ /* Set the repeition counter to zero */
+
+ pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, 0);
+
+ /* Generate an update event to reload the prescaler */
+
+ pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+ }
+ }
+ else
+#endif
+ {
+ /* Generate an update event to reload the prescaler (all timers) */
+
+ pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+ }
+
+ /* Handle channel specific setup */
+
+ ocmode1 = 0;
+ ocmode2 = 0;
+ switch (priv->channel)
+ {
+ case 1: /* PWM Mode configuration: Channel 1 */
+ {
+ /* Select the CCER enable bit for this channel */
+
+ ccenable = ATIM_CCER_CC1E;
+
+ /* Set the CCMR1 mode values (leave CCMR2 zero) */
+
+ ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) |
+ (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) |
+ ATIM_CCMR1_OC1PE;
+
+ /* Set the duty cycle by writing to the CCR register for this channel */
+
+ pwm_putreg(priv, STM32_GTIM_CCR1_OFFSET, (uint16_t)ccr);
+ }
+ break;
+
+ case 2: /* PWM Mode configuration: Channel 2 */
+ {
+ /* Select the CCER enable bit for this channel */
+
+ ccenable = ATIM_CCER_CC2E;
+
+ /* Set the CCMR1 mode values (leave CCMR2 zero) */
+
+ ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) |
+ (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) |
+ ATIM_CCMR1_OC2PE;
+
+ /* Set the duty cycle by writing to the CCR register for this channel */
+
+ pwm_putreg(priv, STM32_GTIM_CCR2_OFFSET, (uint16_t)ccr);
+ }
+ break;
+
+ case 3: /* PWM Mode configuration: Channel3 */
+ {
+ /* Select the CCER enable bit for this channel */
+
+ ccenable = ATIM_CCER_CC3E;
+
+ /* Set the CCMR2 mode values (leave CCMR1 zero) */
+
+ ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) |
+ (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) |
+ ATIM_CCMR2_OC3PE;
+
+ /* Set the duty cycle by writing to the CCR register for this channel */
+
+ pwm_putreg(priv, STM32_GTIM_CCR3_OFFSET, (uint16_t)ccr);
+ }
+ break;
+
+ case 4: /* PWM1 Mode configuration: Channel4 */
+ {
+ /* Select the CCER enable bit for this channel */
+
+ ccenable = ATIM_CCER_CC4E;
+
+ /* Set the CCMR2 mode values (leave CCMR1 zero) */
+
+ ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) |
+ (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) |
+ ATIM_CCMR2_OC4PE;
+
+ /* Set the duty cycle by writing to the CCR register for this channel */
+
+ pwm_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)ccr);
+ }
+ break;
+
+ default:
+ pwmdbg("No such channel: %d\n", priv->channel);
+ return -EINVAL;
+ }
+
+ /* Disable the Channel by resetting the CCxE Bit in the CCER register */
+
+ ccer = pwm_getreg(priv, STM32_GTIM_CCER_OFFSET);
+ ccer &= ~ccenable;
+ pwm_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
+
+ /* Fetch the CR2, CCMR1, and CCMR2 register (already have cr1 and ccer) */
+
+ cr2 = pwm_getreg(priv, STM32_GTIM_CR2_OFFSET);
+ ccmr1 = pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET);
+ ccmr2 = pwm_getreg(priv, STM32_GTIM_CCMR2_OFFSET);
+
+ /* Reset the Output Compare Mode Bits and set the select output compare mode */
+
+ ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE |
+ ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE);
+ ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE |
+ ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE);
+ ccmr1 |= ocmode1;
+ ccmr2 |= ocmode2;
+
+ /* Reset the output polarity level of all channels (selects high polarity)*/
+
+ ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P | ATIM_CCER_CC3P | ATIM_CCER_CC4P);
+
+ /* Enable the output state of the selected channel (only) */
+
+ ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E | ATIM_CCER_CC3E | ATIM_CCER_CC4E);
+ ccer |= ccenable;
+
+ /* Some special setup for advanced timers */
+
+#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM)
+ if (priv->timtype == TIMTYPE_ADVANCED)
+ {
+ uint16_t bdtr;
+
+ /* Reset output N polarity level, output N state, output compare state,
+ * output compare N idle state.
+ */
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP |
+ ATIM_CCER_CC3NE | ATIM_CCER_CC3NP | ATIM_CCER_CC4NP);
+#else
+ ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP |
+ ATIM_CCER_CC3NE | ATIM_CCER_CC3NP);
+#endif
+
+ /* Reset the output compare and output compare N IDLE State */
+
+ cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | ATIM_CR2_OIS2 | ATIM_CR2_OIS2N |
+ ATIM_CR2_OIS3 | ATIM_CR2_OIS3N | ATIM_CR2_OIS4);
+
+ /* Set the main output enable (MOE) bit and clear the OSSI and OSSR
+ * bits in the BDTR register.
+ */
+
+ bdtr = pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET);
+ bdtr &= ~(ATIM_BDTR_OSSI | ATIM_BDTR_OSSR);
+ bdtr |= ATIM_BDTR_MOE;
+ pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, bdtr);
+ }
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ else
+#endif
+#endif
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ {
+ ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP | GTIM_CCER_CC4NP);
+ }
+#endif
+
+ /* Save the modified register values */
+
+ pwm_putreg(priv, STM32_GTIM_CR2_OFFSET, cr2);
+ pwm_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
+ pwm_putreg(priv, STM32_GTIM_CCMR2_OFFSET, ccmr2);
+ pwm_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
+
+ /* Set the ARR Preload Bit */
+
+ cr1 = pwm_getreg(priv, STM32_GTIM_CR1_OFFSET);
+ cr1 |= GTIM_CR1_ARPE;
+ pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+ /* Setup update interrupt. If info->count is > 0, then we can be
+ * assured that pwm_start() has already verified: (1) that this is an
+ * advanced timer, and that (2) the repetitioncount is within range.
+ */
+
+#ifdef CONFIG_PWM_PULSECOUNT
+ if (info->count > 0)
+ {
+ /* Clear all pending interrupts and enable the update interrupt. */
+
+ pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
+ pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, ATIM_DIER_UIE);
+
+ /* Enable the timer */
+
+ cr1 |= GTIM_CR1_CEN;
+ pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+ /* And enable timer interrupts at the NVIC */
+
+ up_enable_irq(priv->irq);
+ }
+ else
+#endif
+ {
+ /* Just enable the timer, leaving all interrupts disabled */
+
+ cr1 |= GTIM_CR1_CEN;
+ pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+ }
+
+ pwm_dumpregs(priv, "After starting");
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_interrupt
+ *
+ * Description:
+ * Handle timer interrupts.
+ *
+ * Input parameters:
+ * priv - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM))
+static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
+{
+ uint16_t regval;
+
+ /* Verify that this is an update interrupt. Nothing else is expected. */
+
+ regval = pwm_getreg(priv, STM32_ATIM_SR_OFFSET);
+ DEBUGASSERT((regval & ATIM_SR_UIF) != 0);
+
+ /* Clear the UIF interrupt bit */
+
+ pwm_putreg(priv, STM32_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF);
+
+ /* Calculate the new count by subtracting the number of pulses
+ * since the last interrupt.
+ */
+
+ if (priv->count <= priv->prev)
+ {
+ /* We are finished. Turn off the mast output to stop the output as
+ * quickly as possible.
+ */
+
+ regval = pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET);
+ regval &= ~ATIM_BDTR_MOE;
+ pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, regval);
+
+ /* Disable first interrtups, stop and reset the timer */
+
+ (void)pwm_stop((FAR struct pwm_lowerhalf_s *)priv);
+
+ /* Then perform the callback into the upper half driver */
+
+ pwm_expired(priv->handle);
+
+ priv->handle = NULL;
+ priv->count = 0;
+ priv->prev = 0;
+ priv->curr = 0;
+ }
+ else
+ {
+ /* Decrement the count of pulses remaining using the number of
+ * pulses generated since the last interrupt.
+ */
+
+ priv->count -= priv->prev;
+
+ /* Set up the next RCR. Set 'prev' to the value of the RCR that
+ * was loaded when the update occurred (just before this interrupt)
+ * and set 'curr' to the current value of the RCR register (which
+ * will bet loaded on the next update event).
+ */
+
+ priv->prev = priv->curr;
+ priv->curr = pwm_pulsecount(priv->count - priv->prev);
+ pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
+ }
+
+ /* Now all of the time critical stuff is done so we can do some debug output */
+
+ pwmllvdbg("Update interrupt SR: %04x prev: %d curr: %d count: %d\n",
+ regval, priv->prev, priv->curr, priv->count);
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: pwm_tim1/8interrupt
+ *
+ * Description:
+ * Handle timer 1 and 8 interrupts.
+ *
+ * Input parameters:
+ * Standard NuttX interrupt inputs
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32_TIM1_PWM)
+static int pwm_tim1interrupt(int irq, void *context)
+{
+ return pwm_interrupt(&g_pwm1dev);
+}
+#endif
+
+#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32_TIM8_PWM)
+static int pwm_tim8interrupt(int irq, void *context)
+{
+ return pwm_interrupt(&g_pwm8dev);
+}
+#endif
+
+/****************************************************************************
+ * Name: pwm_pulsecount
+ *
+ * Description:
+ * Pick an optimal pulse count to program the RCR.
+ *
+ * Input parameters:
+ * count - The total count remaining
+ *
+ * Returned Value:
+ * The recommended pulse count
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM))
+static uint8_t pwm_pulsecount(uint32_t count)
+{
+ /* The the remaining pulse count is less than or equal to the maximum, the
+ * just return the count.
+ */
+
+ if (count <= ATIM_RCR_REP_MAX)
+ {
+ return count;
+ }
+
+ /* Otherwise, we have to be careful. We do not want a small number of
+ * counts at the end because we might have trouble responding fast enough.
+ * If the remaining count is less than 150% of the maximum, then return
+ * half of the maximum. In this case the final sequence will be between 64
+ * and 128.
+ */
+
+ else if (count < (3 * ATIM_RCR_REP_MAX / 2))
+ {
+ return (ATIM_RCR_REP_MAX + 1) >> 1;
+ }
+
+ /* Otherwise, return the maximum. The final count will be 64 or more */
+
+ else
+ {
+ return ATIM_RCR_REP_MAX;
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: pwm_setup
+ *
+ * Description:
+ * This method is called when the driver is opened. The lower half driver
+ * should configure and initialize the device so that it is ready for use.
+ * It should not, however, output pulses until the start method is called.
+ *
+ * Input parameters:
+ * dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure
+ *
+ * Assumptions:
+ * AHB1 or 2 clocking for the GPIOs and timer has already been configured
+ * by the RCC logic at power up.
+ *
+ ****************************************************************************/
+
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev)
+{
+ FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev;
+
+ pwmvdbg("TIM%d pincfg: %08x\n", priv->timid, priv->pincfg);
+ pwm_dumpregs(priv, "Initially");
+
+ /* Configure the PWM output pin, but do not start the timer yet */
+
+ stm32_configgpio(priv->pincfg);
+ pwm_dumpgpio(priv->pincfg, "PWM setup");
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_shutdown
+ *
+ * Description:
+ * This method is called when the driver is closed. The lower half driver
+ * stop pulsed output, free any resources, disable the timer hardware, and
+ * put the system into the lowest possible power usage state
+ *
+ * Input parameters:
+ * dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
+{
+ FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev;
+ uint32_t pincfg;
+
+ pwmvdbg("TIM%d pincfg: %08x\n", priv->timid, priv->pincfg);
+
+ /* Make sure that the output has been stopped */
+
+ pwm_stop(dev);
+
+ /* Then put the GPIO pin back to the default state */
+
+ pincfg = priv->pincfg & (GPIO_PORT_MASK|GPIO_PIN_MASK);
+
+#if defined(CONFIG_STM32_STM32F10XX)
+ pincfg |= (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT);
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ pincfg |= (GPIO_INPUT|GPIO_FLOAT);
+#else
+# error "Unrecognized STM32 chip"
+#endif
+
+ stm32_configgpio(pincfg);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_start
+ *
+ * Description:
+ * (Re-)initialize the timer resources and start the pulsed output
+ *
+ * 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
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PWM_PULSECOUNT
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+ FAR const struct pwm_info_s *info,
+ FAR void *handle)
+{
+ FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev;
+
+ /* Check if a pulsecount has been selected */
+
+ if (info->count > 0)
+ {
+ /* Only the advanced timers (TIM1,8 can support the pulse counting) */
+
+ if (priv->timtype != TIMTYPE_ADVANCED)
+ {
+ pwmdbg("ERROR: TIM%d cannot support pulse count: %d\n",
+ priv->timid, info->count);
+ return -EPERM;
+ }
+ }
+
+ /* Save the handle */
+
+ priv->handle = handle;
+
+ /* Start the time */
+
+ return pwm_timer(priv, info);
+}
+#else
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+ FAR const struct pwm_info_s *info)
+{
+ FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev;
+ return pwm_timer(priv, info);
+}
+#endif
+
+/****************************************************************************
+ * Name: pwm_stop
+ *
+ * Description:
+ * Stop the pulsed output and reset the timer resources
+ *
+ * Input parameters:
+ * dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure
+ *
+ * Assumptions:
+ * This function is called to stop the pulsed output at anytime. This
+ * method is also called from the timer interrupt handler when a repetition
+ * count expires... automatically stopping the timer.
+ *
+ ****************************************************************************/
+
+static int pwm_stop(FAR struct pwm_lowerhalf_s *dev)
+{
+ FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev;
+ uint32_t resetbit;
+ uint32_t regaddr;
+ uint32_t regval;
+ irqstate_t flags;
+
+ pwmvdbg("TIM%d\n", priv->timid);
+
+ /* Disable interrupts momentary to stop any ongoing timer processing and
+ * to prevent any concurrent access to the reset register.
+ */
+
+ flags = irqsave();
+
+ /* Disable further interrupts and stop the timer */
+
+ pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, 0);
+ pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
+
+ /* Determine which timer to reset */
+
+ switch (priv->timid)
+ {
+#ifdef CONFIG_STM32_TIM1_PWM
+ case 1:
+ regaddr = STM32_RCC_APB2RSTR;
+ resetbit = RCC_APB2RSTR_TIM1RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM2_PWM
+ case 2:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM2RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM3_PWM
+ case 3:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM3RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM4_PWM
+ case 4:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM4RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM5_PWM
+ case 5:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM5RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM8_PWM
+ case 8:
+ regaddr = STM32_RCC_APB2RSTR;
+ resetbit = RCC_APB2RSTR_TIM8RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM9_PWM
+ case 9:
+ regaddr = STM32_RCC_APB2RSTR;
+ resetbit = RCC_APB2RSTR_TIM9RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM10_PWM
+ case 10:
+ regaddr = STM32_RCC_APB2RSTR;
+ resetbit = RCC_APB2RSTR_TIM10RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM11_PWM
+ case 11:
+ regaddr = STM32_RCC_APB2RSTR;
+ resetbit = RCC_APB2RSTR_TIM11RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM12_PWM
+ case 12:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM12RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM13_PWM
+ case 13:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM13RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM14_PWM
+ case 14:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM14RST;
+ break;
+#endif
+ }
+
+ /* Reset the timer - stopping the output and putting the timer back
+ * into a state where pwm_start() can be called.
+ */
+
+ regval = getreg32(regaddr);
+ regval |= resetbit;
+ putreg32(regval, regaddr);
+
+ regval &= ~resetbit;
+ putreg32(regval, regaddr);
+ irqrestore(flags);
+
+ pwmvdbg("regaddr: %08x resetbit: %08x\n", regaddr, resetbit);
+ pwm_dumpregs(priv, "After stop");
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_ioctl
+ *
+ * Description:
+ * Lower-half logic may support platform-specific ioctl commands
+ *
+ * Input parameters:
+ * dev - A reference to the lower half PWM driver state structure
+ * cmd - The ioctl command
+ * arg - The argument accompanying the ioctl command
+ *
+ * Returned Value:
+ * Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg)
+{
+#ifdef CONFIG_DEBUG_PWM
+ FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev;
+
+ /* There are no platform-specific ioctl commands */
+
+ pwmvdbg("TIM%d\n", priv->timid);
+#endif
+ return -ENOTTY;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_pwminitialize
+ *
+ * Description:
+ * Initialize one timer for use with the upper_level PWM driver.
+ *
+ * Input Parameters:
+ * timer - A number identifying the timer use. The number of valid timer
+ * IDs varies with the STM32 MCU and MCU family but is somewhere in
+ * the range of {1,..,14}.
+ *
+ * Returned Value:
+ * On success, a pointer to the STM32 lower half PWM driver is returned.
+ * NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct pwm_lowerhalf_s *stm32_pwminitialize(int timer)
+{
+ FAR struct stm32_pwmtimer_s *lower;
+
+ pwmvdbg("TIM%d\n", timer);
+
+ switch (timer)
+ {
+#ifdef CONFIG_STM32_TIM1_PWM
+ case 1:
+ lower = &g_pwm1dev;
+
+ /* Attach but disable the TIM1 update interrupt */
+
+#ifdef CONFIG_PWM_PULSECOUNT
+ irq_attach(lower->irq, pwm_tim1interrupt);
+ up_disable_irq(lower->irq);
+#endif
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM2_PWM
+ case 2:
+ lower = &g_pwm2dev;
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM3_PWM
+ case 3:
+ lower = &g_pwm3dev;
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM4_PWM
+ case 4:
+ lower = &g_pwm4dev;
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM5_PWM
+ case 5:
+ lower = &g_pwm5dev;
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM8_PWM
+ case 8:
+ lower = &g_pwm8dev;
+
+ /* Attach but disable the TIM8 update interrupt */
+
+#ifdef CONFIG_PWM_PULSECOUNT
+ irq_attach(lower->irq, pwm_tim8interrupt);
+ up_disable_irq(lower->irq);
+#endif
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM9_PWM
+ case 9:
+ lower = &g_pwm9dev;
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM10_PWM
+ case 10:
+ lower = &g_pwm10dev;
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM11_PWM
+ case 11:
+ lower = &g_pwm11dev;
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM12_PWM
+ case 12:
+ lower = &g_pwm12dev;
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM13_PWM
+ case 13:
+ lower = &g_pwm13dev;
+ break;
+#endif
+
+#ifdef CONFIG_STM32_TIM14_PWM
+ case 14:
+ lower = &g_pwm14dev;
+ break;
+#endif
+
+ default:
+ pwmdbg("No such timer configured\n");
+ return NULL;
+ }
+
+ return (FAR struct pwm_lowerhalf_s *)lower;
+}
+
+#endif /* CONFIG_STM32_TIMn_PWM, n = 1,...,14 */
diff --git a/nuttx/arch/arm/src/stm32/stm32_pwm.h b/nuttx/arch/arm/src/stm32/stm32_pwm.h
new file mode 100644
index 000000000..c51c56950
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_pwm.h
@@ -0,0 +1,370 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_pwm.h
+ *
+ * Copyright (C) 2011 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_STM32_STM32_PWM_H
+#define __ARCH_ARM_SRC_STM32_STM32_PWM_H
+
+/* The STM32 does not have dedicated PWM hardware. Rather, pulsed output control
+ * is a capabilitiy of the STM32 timers. The logic in this file implements the
+ * lower half of the standard, NuttX PWM interface using the STM32 timers. That
+ * interface is described in include/nuttx/pwm.h.
+ */
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* Timer devices may be used for different purposes. One special purpose is
+ * to generate modulated outputs for such things as motor control. If CONFIG_STM32_TIMn
+ * is defined then the CONFIG_STM32_TIMn_PWM must also be defined to indicate that
+ * timer "n" is intended to be used for pulsed output signal generation.
+ */
+
+#ifndef CONFIG_STM32_TIM1
+# undef CONFIG_STM32_TIM1_PWM
+#endif
+#ifndef CONFIG_STM32_TIM2
+# undef CONFIG_STM32_TIM2_PWM
+#endif
+#ifndef CONFIG_STM32_TIM3
+# undef CONFIG_STM32_TIM3_PWM
+#endif
+#ifndef CONFIG_STM32_TIM4
+# undef CONFIG_STM32_TIM4_PWM
+#endif
+#ifndef CONFIG_STM32_TIM5
+# undef CONFIG_STM32_TIM5_PWM
+#endif
+#ifndef CONFIG_STM32_TIM8
+# undef CONFIG_STM32_TIM8_PWM
+#endif
+#ifndef CONFIG_STM32_TIM9
+# undef CONFIG_STM32_TIM9_PWM
+#endif
+#ifndef CONFIG_STM32_TIM10
+# undef CONFIG_STM32_TIM10_PWM
+#endif
+#ifndef CONFIG_STM32_TIM11
+# undef CONFIG_STM32_TIM11_PWM
+#endif
+#ifndef CONFIG_STM32_TIM12
+# undef CONFIG_STM32_TIM12_PWM
+#endif
+#ifndef CONFIG_STM32_TIM13
+# undef CONFIG_STM32_TIM13_PWM
+#endif
+#ifndef CONFIG_STM32_TIM14
+# undef CONFIG_STM32_TIM14_PWM
+#endif
+
+/* The basic timers (timer 6 and 7) are not capable of generating output pulses */
+
+#undef CONFIG_STM32_TIM6_PWM
+#undef CONFIG_STM32_TIM7_PWM
+
+/* Check if PWM support for any channel is enabled. */
+
+#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM2_PWM) || \
+ defined(CONFIG_STM32_TIM3_PWM) || defined(CONFIG_STM32_TIM4_PWM) || \
+ defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM8_PWM) || \
+ defined(CONFIG_STM32_TIM9_PWM) || defined(CONFIG_STM32_TIM10_PWM) || \
+ defined(CONFIG_STM32_TIM11_PWM) || defined(CONFIG_STM32_TIM12_PWM) || \
+ defined(CONFIG_STM32_TIM13_PWM) || defined(CONFIG_STM32_TIM14_PWM)
+
+#include <arch/board/board.h>
+#include "chip/stm32_tim.h"
+
+/* For each timer that is enabled for PWM usage, we need the following additional
+ * configuration settings:
+ *
+ * CONFIG_STM32_TIMx_CHANNEL - Specifies the timer output channel {1,..,4}
+ * PWM_TIMx_CHn - One of the values defined in chip/stm32*_pinmap.h. In the case
+ * where there are multiple pin selections, the correct setting must be provided
+ * in the arch/board/board.h file.
+ *
+ * NOTE: The STM32 timers are each capable of generating different signals on
+ * each of the four channels with different duty cycles. That capability is
+ * not supported by this driver: Only one output channel per timer.
+ */
+
+#ifdef CONFIG_STM32_TIM1_PWM
+# if !defined(CONFIG_STM32_TIM1_CHANNEL)
+# error "CONFIG_STM32_TIM1_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM1_CHANNEL == 1
+# define PWM_TIM1_PINCFG GPIO_TIM1_CH1OUT
+# elif CONFIG_STM32_TIM1_CHANNEL == 2
+# define PWM_TIM1_PINCFG GPIO_TIM1_CH2OUT
+# elif CONFIG_STM32_TIM1_CHANNEL == 3
+# define PWM_TIM1_PINCFG GPIO_TIM1_CH3OUT
+# elif CONFIG_STM32_TIM1_CHANNEL == 4
+# define PWM_TIM1_PINCFG GPIO_TIM1_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM1_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM2_PWM
+# if !defined(CONFIG_STM32_TIM2_CHANNEL)
+# error "CONFIG_STM32_TIM2_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM2_CHANNEL == 1
+# define PWM_TIM2_PINCFG GPIO_TIM2_CH1OUT
+# elif CONFIG_STM32_TIM2_CHANNEL == 2
+# define PWM_TIM2_PINCFG GPIO_TIM2_CH2OUT
+# elif CONFIG_STM32_TIM2_CHANNEL == 3
+# define PWM_TIM2_PINCFG GPIO_TIM2_CH3OUT
+# elif CONFIG_STM32_TIM2_CHANNEL == 4
+# define PWM_TIM2_PINCFG GPIO_TIM2_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM2_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM3_PWM
+# if !defined(CONFIG_STM32_TIM3_CHANNEL)
+# error "CONFIG_STM32_TIM3_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM3_CHANNEL == 1
+# define PWM_TIM3_PINCFG GPIO_TIM3_CH1OUT
+# elif CONFIG_STM32_TIM3_CHANNEL == 2
+# define PWM_TIM3_PINCFG GPIO_TIM3_CH2OUT
+# elif CONFIG_STM32_TIM3_CHANNEL == 3
+# define PWM_TIM3_PINCFG GPIO_TIM3_CH3OUT
+# elif CONFIG_STM32_TIM3_CHANNEL == 4
+# define PWM_TIM3_PINCFG GPIO_TIM3_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM3_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM4_PWM
+# if !defined(CONFIG_STM32_TIM4_CHANNEL)
+# error "CONFIG_STM32_TIM4_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM4_CHANNEL == 1
+# define PWM_TIM4_PINCFG GPIO_TIM4_CH1OUT
+# elif CONFIG_STM32_TIM4_CHANNEL == 2
+# define PWM_TIM4_PINCFG GPIO_TIM4_CH2OUT
+# elif CONFIG_STM32_TIM4_CHANNEL == 3
+# define PWM_TIM4_PINCFG GPIO_TIM4_CH3OUT
+# elif CONFIG_STM32_TIM4_CHANNEL == 4
+# define PWM_TIM4_PINCFG GPIO_TIM4_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM4_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM5_PWM
+# if !defined(CONFIG_STM32_TIM5_CHANNEL)
+# error "CONFIG_STM32_TIM5_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM5_CHANNEL == 1
+# define PWM_TIM5_PINCFG GPIO_TIM5_CH1OUT
+# elif CONFIG_STM32_TIM5_CHANNEL == 2
+# define PWM_TIM5_PINCFG GPIO_TIM5_CH2OUT
+# elif CONFIG_STM32_TIM5_CHANNEL == 3
+# define PWM_TIM5_PINCFG GPIO_TIM5_CH3OUT
+# elif CONFIG_STM32_TIM5_CHANNEL == 4
+# define PWM_TIM5_PINCFG GPIO_TIM5_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM5_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM8_PWM
+# if !defined(CONFIG_STM32_TIM8_CHANNEL)
+# error "CONFIG_STM32_TIM8_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM8_CHANNEL == 1
+# define PWM_TIM8_PINCFG GPIO_TIM8_CH1OUT
+# elif CONFIG_STM32_TIM8_CHANNEL == 2
+# define PWM_TIM8_PINCFG GPIO_TIM8_CH2OUT
+# elif CONFIG_STM32_TIM8_CHANNEL == 3
+# define PWM_TIM8_PINCFG GPIO_TIM8_CH3OUT
+# elif CONFIG_STM32_TIM8_CHANNEL == 4
+# define PWM_TIM8_PINCFG GPIO_TIM8_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM8_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM9_PWM
+# if !defined(CONFIG_STM32_TIM9_CHANNEL)
+# error "CONFIG_STM32_TIM9_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM9_CHANNEL == 1
+# define PWM_TIM9_PINCFG GPIO_TIM9_CH1OUT
+# elif CONFIG_STM32_TIM9_CHANNEL == 2
+# define PWM_TIM9_PINCFG GPIO_TIM9_CH2OUT
+# elif CONFIG_STM32_TIM9_CHANNEL == 3
+# define PWM_TIM9_PINCFG GPIO_TIM9_CH3OUT
+# elif CONFIG_STM32_TIM9_CHANNEL == 4
+# define PWM_TIM9_PINCFG GPIO_TIM9_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM9_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM10_PWM
+# if !defined(CONFIG_STM32_TIM10_CHANNEL)
+# error "CONFIG_STM32_TIM10_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM10_CHANNEL == 1
+# define PWM_TIM10_PINCFG GPIO_TIM10_CH1OUT
+# elif CONFIG_STM32_TIM10_CHANNEL == 2
+# define PWM_TIM10_PINCFG GPIO_TIM10_CH2OUT
+# elif CONFIG_STM32_TIM10_CHANNEL == 3
+# define PWM_TIM10_PINCFG GPIO_TIM10_CH3OUT
+# elif CONFIG_STM32_TIM10_CHANNEL == 4
+# define PWM_TIM10_PINCFG GPIO_TIM10_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM10_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM11_PWM
+# if !defined(CONFIG_STM32_TIM11_CHANNEL)
+# error "CONFIG_STM32_TIM11_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM11_CHANNEL == 1
+# define PWM_TIM11_PINCFG GPIO_TIM11_CH1OUT
+# elif CONFIG_STM32_TIM11_CHANNEL == 2
+# define PWM_TIM11_PINCFG GPIO_TIM11_CH2OUT
+# elif CONFIG_STM32_TIM11_CHANNEL == 3
+# define PWM_TIM11_PINCFG GPIO_TIM11_CH3OUT
+# elif CONFIG_STM32_TIM11_CHANNEL == 4
+# define PWM_TIM11_PINCFG GPIO_TIM11_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM11_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM12_PWM
+# if !defined(CONFIG_STM32_TIM12_CHANNEL)
+# error "CONFIG_STM32_TIM12_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM12_CHANNEL == 1
+# define PWM_TIM12_PINCFG GPIO_TIM12_CH1OUT
+# elif CONFIG_STM32_TIM12_CHANNEL == 2
+# define PWM_TIM12_PINCFG GPIO_TIM12_CH2OUT
+# elif CONFIG_STM32_TIM12_CHANNEL == 3
+# define PWM_TIM12_PINCFG GPIO_TIM12_CH3OUT
+# elif CONFIG_STM32_TIM12_CHANNEL == 4
+# define PWM_TIM12_PINCFG GPIO_TIM12_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM12_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM13_PWM
+# if !defined(CONFIG_STM32_TIM13_CHANNEL)
+# error "CONFIG_STM32_TIM13_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM13_CHANNEL == 1
+# define PWM_TIM13_PINCFG GPIO_TIM13_CH1OUT
+# elif CONFIG_STM32_TIM13_CHANNEL == 2
+# define PWM_TIM13_PINCFG GPIO_TIM13_CH2OUT
+# elif CONFIG_STM32_TIM13_CHANNEL == 3
+# define PWM_TIM13_PINCFG GPIO_TIM13_CH3OUT
+# elif CONFIG_STM32_TIM13_CHANNEL == 4
+# define PWM_TIM13_PINCFG GPIO_TIM13_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM13_CHANNEL"
+# endif
+#endif
+
+#ifdef CONFIG_STM32_TIM14_PWM
+# if !defined(CONFIG_STM32_TIM14_CHANNEL)
+# error "CONFIG_STM32_TIM14_CHANNEL must be provided"
+# elif CONFIG_STM32_TIM14_CHANNEL == 1
+# define PWM_TIM14_PINCFG GPIO_TIM14_CH1OUT
+# elif CONFIG_STM32_TIM14_CHANNEL == 2
+# define PWM_TIM14_PINCFG GPIO_TIM14_CH2OUT
+# elif CONFIG_STM32_TIM14_CHANNEL == 3
+# define PWM_TIM14_PINCFG GPIO_TIM14_CH3OUT
+# elif CONFIG_STM32_TIM14_CHANNEL == 4
+# define PWM_TIM14_PINCFG GPIO_TIM14_CH4OUT
+# else
+# error "Unsupported value of CONFIG_STM32_TIM14_CHANNEL"
+# endif
+#endif
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_pwminitialize
+ *
+ * Description:
+ * Initialize one timer for use with the upper_level PWM driver.
+ *
+ * Input Parameters:
+ * timer - A number identifying the timer use. The number of valid timer
+ * IDs varies with the STM32 MCU and MCU family but is somewhere in
+ * the range of {1,..,14}.
+ *
+ * Returned Value:
+ * On success, a pointer to the STM32 lower half PWM driver is returned.
+ * NULL is returned on any failure.
+ *
+ ************************************************************************************/
+
+EXTERN FAR struct pwm_lowerhalf_s *stm32_pwminitialize(int timer);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_STM32_TIMx_PWM */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_PWM_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_pwr.c b/nuttx/arch/arm/src/stm32/stm32_pwr.c
new file mode 100644
index 000000000..bada048e3
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_pwr.c
@@ -0,0 +1,98 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_pwr.c
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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 <nuttx/arch.h>
+
+#include <stdint.h>
+#include <errno.h>
+
+#include "up_arch.h"
+#include "stm32_pwr.h"
+
+#if defined(CONFIG_STM32_PWR)
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+static inline uint16_t stm32_pwr_getreg(uint8_t offset)
+{
+ return getreg32(STM32_PWR_BASE + offset);
+}
+
+static inline void stm32_pwr_putreg(uint8_t offset, uint16_t value)
+{
+ putreg32(value, STM32_PWR_BASE + offset);
+}
+
+static inline void stm32_pwr_modifyreg(uint8_t offset, uint16_t clearbits, uint16_t setbits)
+{
+ modifyreg32(STM32_PWR_BASE + offset, clearbits, setbits);
+}
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_pwr_enablebkp
+ *
+ * Description:
+ * Enables access to the backup domain (RTC registers, RTC backup data registers
+ * and backup SRAM).
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Values:
+ * None
+ *
+ ************************************************************************************/
+
+void stm32_pwr_enablebkp(void)
+{
+ stm32_pwr_modifyreg(STM32_PWR_CR_OFFSET, 0, PWR_CR_DBP);
+}
+
+#endif // defined(CONFIG_STM32_PWR)
diff --git a/nuttx/arch/arm/src/stm32/stm32_pwr.h b/nuttx/arch/arm/src/stm32/stm32_pwr.h
new file mode 100644
index 000000000..56aee49b6
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_pwr.h
@@ -0,0 +1,89 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_pwr.h
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_STM32_PWR_H
+#define __ARCH_ARM_SRC_STM32_STM32_PWR_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_pwr.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_pwr_enablebkp
+ *
+ * Description:
+ * Enables access to the backup domain (RTC registers, RTC backup data registers
+ * and backup SRAM).
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Values:
+ * None
+ *
+ ************************************************************************************/
+
+EXTERN void stm32_pwr_enablebkp(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_PWR_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_qencoder.c b/nuttx/arch/arm/src/stm32/stm32_qencoder.c
new file mode 100644
index 000000000..8553296f9
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_qencoder.c
@@ -0,0 +1,1228 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_qencoder.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Authors: Gregory Nutt <gnutt@nuttx.org>
+ * Diego Sanchez <dsanchez@nx-engineering.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/sensors/qencoder.h>
+
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "stm32_internal.h"
+#include "stm32_gpio.h"
+#include "stm32_tim.h"
+#include "stm32_qencoder.h"
+
+#ifdef CONFIG_QENCODER
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Clocking *************************************************************************/
+/* The CLKOUT value should not exceed the CLKIN value */
+
+#if defined(CONFIG_STM32_TIM1_QE) && CONFIG_STM32_TIM1_QECLKOUT > STM32_APB2_TIM1_CLKIN
+# warning "CONFIG_STM32_TIM1_QECLKOUT exceeds STM32_APB2_TIM1_CLKIN"
+#endif
+
+#if defined(CONFIG_STM32_TIM2_QE) && CONFIG_STM32_TIM2_QECLKOUT > STM32_APB1_TIM2_CLKIN
+# warning "CONFIG_STM32_TIM2_QECLKOUT exceeds STM32_APB2_TIM2_CLKIN"
+#endif
+
+#if defined(CONFIG_STM32_TIM3_QE) && CONFIG_STM32_TIM3_QECLKOUT > STM32_APB1_TIM3_CLKIN
+# warning "CONFIG_STM32_TIM3_QECLKOUT exceeds STM32_APB2_TIM3_CLKIN"
+#endif
+
+#if defined(CONFIG_STM32_TIM4_QE) && CONFIG_STM32_TIM4_QECLKOUT > STM32_APB1_TIM4_CLKIN
+# warning "CONFIG_STM32_TIM4_QECLKOUT exceeds STM32_APB2_TIM4_CLKIN"
+#endif
+
+#if defined(CONFIG_STM32_TIM5_QE) && CONFIG_STM32_TIM5_QECLKOUT > STM32_APB1_TIM5_CLKIN
+# warning "CONFIG_STM32_TIM5_QECLKOUT exceeds STM32_APB2_TIM5_CLKIN"
+#endif
+
+#if defined(CONFIG_STM32_TIM8_QE) && CONFIG_STM32_TIM8_QECLKOUT > STM32_APB2_TIM8_CLKIN
+# warning "CONFIG_STM32_TIM8_QECLKOUT exceeds STM32_APB2_TIM8_CLKIN"
+#endif
+
+/* Timers ***************************************************************************/
+/* On the F1 series, all timers are 16-bit. */
+
+#undef HAVE_32BIT_TIMERS
+#undef HAVE_16BIT_TIMERS
+
+#if defined(CONFIG_STM32_STM32F10XX)
+
+# define HAVE_16BIT_TIMERS 1
+
+ /* The width in bits of each timer */
+
+# define TIM1_BITWIDTH 16
+# define TIM2_BITWIDTH 16
+# define TIM3_BITWIDTH 16
+# define TIM4_BITWIDTH 16
+# define TIM5_BITWIDTH 16
+# define TIM8_BITWIDTH 16
+
+/* On the F4 series, TIM2 and TIM5 are 32-bit. All of the rest are 16-bit */
+
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+
+ /* If TIM2 or TIM5 are enabled, then we have 32-bit timers */
+
+# if defined(CONFIG_STM32_TIM2_QE) || defined(CONFIG_STM32_TIM5_QE)
+# define HAVE_32BIT_TIMERS 1
+# endif
+
+ /* If TIM1,3,4, or 8 are enabled, then we have 16-bit timers */
+
+# if defined(CONFIG_STM32_TIM1_QE) || defined(CONFIG_STM32_TIM3_QE) || \
+ defined(CONFIG_STM32_TIM4_QE) || defined(CONFIG_STM32_TIM8_QE)
+# define HAVE_16BIT_TIMERS 1
+# endif
+
+ /* The width in bits of each timer */
+
+# define TIM1_BITWIDTH 16
+# define TIM2_BITWIDTH 32
+# define TIM3_BITWIDTH 16
+# define TIM4_BITWIDTH 16
+# define TIM5_BITWIDTH 32
+# define TIM8_BITWIDTH 16
+#endif
+
+/* Do we need to support mixed 16- and 32-bit timers */
+
+#undef HAVE_MIXEDWIDTH_TIMERS
+#if defined(HAVE_16BIT_TIMERS) && defined(HAVE_32BIT_TIMERS)
+# define HAVE_MIXEDWIDTH_TIMERS 1
+#endif
+
+/* Debug ****************************************************************************/
+/* Non-standard debug that may be enabled just for testing the quadrature encoder */
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_DEBUG_QENCODER
+#endif
+
+#ifdef CONFIG_DEBUG_QENCODER
+# define qedbg dbg
+# define qelldbg lldbg
+# ifdef CONFIG_DEBUG_VERBOSE
+# define qevdbg vdbg
+# define qellvdbg llvdbg
+# define qe_dumpgpio(p,m) stm32_dumpgpio(p,m)
+# else
+# define qevdbg(x...)
+# define qellvdbg(x...)
+# define qe_dumpgpio(p,m)
+# endif
+#else
+# define qedbg(x...)
+# define qelldbg(x...)
+# define qevdbg(x...)
+# define qellvdbg(x...)
+# define qe_dumpgpio(p,m)
+#endif
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+
+/* Constant configuration structure that is retained in FLASH */
+
+struct stm32_qeconfig_s
+{
+ uint8_t timid; /* Timer ID {1,2,3,4,5,8} */
+ uint8_t irq; /* Timer update IRQ */
+#ifdef HAVE_MIXEDWIDTH_TIMERS
+ uint8_t width; /* Timer width (16- or 32-bits) */
+#endif
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ uint32_t ti1cfg; /* TI1 input pin configuration (20-bit encoding) */
+ uint32_t ti2cfg; /* TI2 input pin configuration (20-bit encoding) */
+#else
+ uint16_t ti1cfg; /* TI1 input pin configuration (16-bit encoding) */
+ uint16_t ti2cfg; /* TI2 input pin configuration (16-bit encoding) */
+#endif
+ uint32_t base; /* Register base address */
+ uint32_t psc; /* Timer input clock prescaler */
+ xcpt_t handler; /* Interrupt handler for this IRQ */
+};
+
+/* Overall, RAM-based state structure */
+
+struct stm32_lowerhalf_s
+{
+ /* The first field of this state structure must be a pointer to the lower-
+ * half callback structure:
+ */
+
+ FAR const struct qe_ops_s *ops; /* Lower half callback structure */
+
+ /* STM32 driver-specific fields: */
+
+ FAR const struct stm32_qeconfig_s *config; /* static onfiguration */
+
+ bool inuse; /* True: The lower-half driver is in-use */
+
+#ifdef HAVE_16BIT_TIMERS
+ volatile int32_t position; /* The current position offset */
+#endif
+};
+
+/************************************************************************************
+ * Private Function Prototypes
+ ************************************************************************************/
+/* Helper functions */
+
+static uint16_t stm32_getreg16(struct stm32_lowerhalf_s *priv, int offset);
+static void stm32_putreg16(struct stm32_lowerhalf_s *priv, int offset, uint16_t value);
+static uint32_t stm32_getreg32(FAR struct stm32_lowerhalf_s *priv, int offset);
+static void stm32_putreg32(FAR struct stm32_lowerhalf_s *priv, int offset, uint32_t value);
+
+#if defined(CONFIG_DEBUG_QENCODER) && defined(CONFIG_DEBUG_VERBOSE)
+static void stm32_dumpregs(struct stm32_lowerhalf_s *priv, FAR const char *msg);
+#else
+# define stm32_dumpregs(priv,msg)
+#endif
+
+static FAR struct stm32_lowerhalf_s *stm32_tim2lower(int tim);
+
+/* Interrupt handling */
+
+#ifdef HAVE_16BIT_TIMERS
+static int stm32_interrupt(FAR struct stm32_lowerhalf_s *priv);
+#if defined(CONFIG_STM32_TIM1_QE) && TIM1_BITWIDTH == 16
+static int stm32_tim1interrupt(int irq, FAR void *context);
+#endif
+#if defined(CONFIG_STM32_TIM2_QE) && TIM2_BITWIDTH == 16
+static int stm32_tim2interrupt(int irq, FAR void *context);
+#endif
+#if defined(CONFIG_STM32_TIM3_QE) && TIM3_BITWIDTH == 16
+static int stm32_tim3interrupt(int irq, FAR void *context);
+#endif
+#if defined(CONFIG_STM32_TIM4_QE) && TIM4_BITWIDTH == 16
+static int stm32_tim4interrupt(int irq, FAR void *context);
+#endif
+#if defined(CONFIG_STM32_TIM5_QE) && TIM5_BITWIDTH == 16
+static int stm32_tim5interrupt(int irq, FAR void *context);
+#endif
+#if defined(CONFIG_STM32_TIM8_QE) && TIM8_BITWIDTH == 16
+static int stm32_tim8interrupt(int irq, FAR void *context);
+#endif
+#endif
+
+/* Lower-half Quadrature Encoder Driver Methods */
+
+static int stm32_setup(FAR struct qe_lowerhalf_s *lower);
+static int stm32_shutdown(FAR struct qe_lowerhalf_s *lower);
+static int stm32_position(FAR struct qe_lowerhalf_s *lower, int32_t *pos);
+static int stm32_reset(FAR struct qe_lowerhalf_s *lower);
+static int stm32_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, unsigned long arg);
+
+/************************************************************************************
+ * Private Data
+ ************************************************************************************/
+/* The lower half callback structure */
+
+static const struct qe_ops_s g_qecallbacks =
+{
+ .setup = stm32_setup,
+ .shutdown = stm32_shutdown,
+ .position = stm32_position,
+ .reset = stm32_reset,
+ .ioctl = stm32_ioctl,
+};
+
+/* Per-timer state structures */
+
+#ifdef CONFIG_STM32_TIM1_QE
+static const struct stm32_qeconfig_s g_tim1config =
+{
+ .timid = 1,
+ .irq = STM32_IRQ_TIM1UP,
+#ifdef HAVE_MIXEDWIDTH_TIMERS
+ .width = TIM1_BITWIDTH,
+#endif
+ .base = STM32_TIM1_BASE,
+ .psc = (STM32_APB2_TIM1_CLKIN / CONFIG_STM32_TIM1_QECLKOUT) - 1,
+ .ti1cfg = GPIO_TIM1_CH1IN,
+ .ti2cfg = GPIO_TIM1_CH2IN,
+#if TIM1_BITWIDTH == 16
+ .handler = stm32_tim1interrupt,
+#endif
+};
+
+static struct stm32_lowerhalf_s g_tim1lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_tim1config,
+ .inuse = false,
+};
+
+#endif
+
+#ifdef CONFIG_STM32_TIM2_QE
+static const struct stm32_qeconfig_s g_tim2config =
+{
+ .timid = 2,
+ .irq = STM32_IRQ_TIM2,
+#ifdef HAVE_MIXEDWIDTH_TIMERS
+ .width = TIM2_BITWIDTH,
+#endif
+ .base = STM32_TIM2_BASE,
+ .psc = (STM32_APB1_TIM2_CLKIN / CONFIG_STM32_TIM2_QECLKOUT) - 1,
+ .ti1cfg = GPIO_TIM2_CH1IN,
+ .ti2cfg = GPIO_TIM2_CH2IN,
+#if TIM2_BITWIDTH == 16
+ .handler = stm32_tim2interrupt,
+#endif
+};
+
+static struct stm32_lowerhalf_s g_tim2lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_tim2config,
+ .inuse = false,
+};
+
+#endif
+
+#ifdef CONFIG_STM32_TIM3_QE
+static const struct stm32_qeconfig_s g_tim3config =
+{
+ .timid = 3,
+ .irq = STM32_IRQ_TIM3,
+#ifdef HAVE_MIXEDWIDTH_TIMERS
+ .width = TIM3_BITWIDTH,
+#endif
+ .base = STM32_TIM3_BASE,
+ .psc = (STM32_APB1_TIM3_CLKIN / CONFIG_STM32_TIM3_QECLKOUT) - 1,
+ .ti1cfg = GPIO_TIM3_CH1IN,
+ .ti2cfg = GPIO_TIM3_CH2IN,
+#if TIM3_BITWIDTH == 16
+ .handler = stm32_tim3interrupt,
+#endif
+};
+
+static struct stm32_lowerhalf_s g_tim3lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_tim3config,
+ .inuse = false,
+};
+
+#endif
+
+#ifdef CONFIG_STM32_TIM4_QE
+static const struct stm32_qeconfig_s g_tim4config =
+{
+ .timid = 4,
+ .irq = STM32_IRQ_TIM4,
+#ifdef HAVE_MIXEDWIDTH_TIMERS
+ .width = TIM4_BITWIDTH,
+#endif
+ .base = STM32_TIM4_BASE,
+ .psc = (STM32_APB1_TIM4_CLKIN / CONFIG_STM32_TIM4_QECLKOUT) - 1,
+ .ti1cfg = GPIO_TIM4_CH1IN,
+ .ti2cfg = GPIO_TIM4_CH2IN,
+#if TIM4_BITWIDTH == 16
+ .handler = stm32_tim4interrupt,
+#endif
+};
+
+static struct stm32_lowerhalf_s g_tim4lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_tim4config,
+ .inuse = false,
+};
+
+#endif
+
+#ifdef CONFIG_STM32_TIM5_QE
+static const struct stm32_qeconfig_s g_tim5config =
+{
+ .timid = 5,
+ .irq = STM32_IRQ_TIM5,
+#ifdef HAVE_MIXEDWIDTH_TIMERS
+ .width = TIM5_BITWIDTH,
+#endif
+ .base = STM32_TIM5_BASE,
+ .psc = (STM32_APB1_TIM5_CLKIN / CONFIG_STM32_TIM5_QECLKOUT) - 1,
+ .ti1cfg = GPIO_TIM5_CH1IN,
+ .ti2cfg = GPIO_TIM5_CH2IN,
+#if TIM5_BITWIDTH == 16
+ .handler = stm32_tim5interrupt,
+#endif
+};
+
+static struct stm32_lowerhalf_s g_tim5lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_tim5config,
+ .inuse = false,
+};
+
+#endif
+
+#ifdef CONFIG_STM32_TIM8_QE
+static const struct stm32_qeconfig_s g_tim8config =
+{
+ .timid = 8,
+ .irq = STM32_IRQ_TIM8UP,
+#ifdef HAVE_MIXEDWIDTH_TIMERS
+ .width = TIM8_BITWIDTH,
+#endif
+ .base = STM32_TIM8_BASE,
+ .psc = (STM32_APB2_TIM8_CLKIN / CONFIG_STM32_TIM8_QECLKOUT) - 1,
+ .ti1cfg = GPIO_TIM8_CH1IN,
+ .ti2cfg = GPIO_TIM8_CH2IN,
+#if TIM8_BITWIDTH == 16
+ .handler = stm32_tim8interrupt,
+#endif
+};
+
+static struct stm32_lowerhalf_s g_tim8lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_tim8config,
+ .inuse = false,
+};
+
+#endif
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_getreg16
+ *
+ * Description:
+ * Read the value of a 16-bit timer register.
+ *
+ * Input Parameters:
+ * priv - A reference to the lower half status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * The current contents of the specified register
+ *
+ ************************************************************************************/
+
+static uint16_t stm32_getreg16(struct stm32_lowerhalf_s *priv, int offset)
+{
+ return getreg16(priv->config->base + offset);
+}
+
+/************************************************************************************
+ * Name: stm32_putreg16
+ *
+ * Description:
+ * Write a value to a 16-bit timer register.
+ *
+ * Input Parameters:
+ * priv - A reference to the lower half status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static void stm32_putreg16(struct stm32_lowerhalf_s *priv, int offset, uint16_t value)
+{
+ putreg16(value, priv->config->base + offset);
+}
+
+/************************************************************************************
+ * Name: stm32_getreg32
+ *
+ * Description:
+ * Read the value of a 32-bit timer register. This applies only for the STM32 F4
+ * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5 (but works OK
+ * with the 16-bit TIM1,8 and F1 registers as well).
+ *
+ * Input Parameters:
+ * priv - A reference to the lower half status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * The current contents of the specified register
+ *
+ ************************************************************************************/
+
+static uint32_t stm32_getreg32(FAR struct stm32_lowerhalf_s *priv, int offset)
+{
+ return getreg32(priv->config->base + offset);
+}
+
+/************************************************************************************
+ * Name: stm32_putreg16
+ *
+ * Description:
+ * Write a value to a 32-bit timer register. This applies only for the STM32 F4
+ * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5 (but works OK
+ * with the 16-bit TIM1,8 and F1 registers).
+ *
+ * Input Parameters:
+ * priv - A reference to the lower half status
+ * offset - The offset to the register to read
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static void stm32_putreg32(FAR struct stm32_lowerhalf_s *priv, int offset, uint32_t value)
+{
+ putreg32(value, priv->config->base + offset);
+}
+
+/****************************************************************************
+ * Name: stm32_dumpregs
+ *
+ * Description:
+ * Dump all timer registers.
+ *
+ * Input parameters:
+ * priv - A reference to the QENCODER block status
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_DEBUG_QENCODER) && defined(CONFIG_DEBUG_VERBOSE)
+static void stm32_dumpregs(struct stm32_lowerhalf_s *priv, FAR const char *msg)
+{
+ qevdbg("%s:\n", msg);
+ qevdbg(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n",
+ stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_CR2_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_SMCR_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_DIER_OFFSET));
+ qevdbg(" SR: %04x EGR: %04x CCMR1: %04x CCMR2: %04x\n",
+ stm32_getreg16(priv, STM32_GTIM_SR_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_EGR_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_CCMR2_OFFSET));
+ qevdbg(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n",
+ stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_CNT_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_PSC_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_ARR_OFFSET));
+ qevdbg(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n",
+ stm32_getreg16(priv, STM32_GTIM_CCR1_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_CCR2_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_CCR3_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_CCR4_OFFSET));
+#if defined(CONFIG_STM32_TIM1_QENCODER) || defined(CONFIG_STM32_TIM8_QENCODER)
+ if (priv->timtype == TIMTYPE_ADVANCED)
+ {
+ qevdbg(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n",
+ stm32_getreg16(priv, STM32_ATIM_RCR_OFFSET),
+ stm32_getreg16(priv, STM32_ATIM_BDTR_OFFSET),
+ stm32_getreg16(priv, STM32_ATIM_DCR_OFFSET),
+ stm32_getreg16(priv, STM32_ATIM_DMAR_OFFSET));
+ }
+ else
+#endif
+ {
+ qevdbg(" DCR: %04x DMAR: %04x\n",
+ stm32_getreg16(priv, STM32_GTIM_DCR_OFFSET),
+ stm32_getreg16(priv, STM32_GTIM_DMAR_OFFSET));
+ }
+}
+#endif
+
+/************************************************************************************
+ * Name: stm32_tim2lower
+ *
+ * Description:
+ * Map a timer number to a device structure
+ *
+ ************************************************************************************/
+
+static FAR struct stm32_lowerhalf_s *stm32_tim2lower(int tim)
+{
+ switch (tim)
+ {
+#ifdef CONFIG_STM32_TIM1_QE
+ case 1:
+ return &g_tim1lower;
+#endif
+#ifdef CONFIG_STM32_TIM2_QE
+ case 2:
+ return &g_tim2lower;
+#endif
+#ifdef CONFIG_STM32_TIM3_QE
+ case 3:
+#endif
+#ifdef CONFIG_STM32_TIM4_QE
+ case 4:
+ return &g_tim4lower;
+#endif
+#ifdef CONFIG_STM32_TIM5_QE
+ case 5:
+ return &g_tim5lower;
+#endif
+#ifdef CONFIG_STM32_TIM8_QE
+ case 8:
+ return &g_tim8lower;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+/************************************************************************************
+ * Name: stm32_interrupt
+ *
+ * Description:
+ * Common timer interrupt handling. NOTE: Only 16-bit timers require timer
+ * interrupts.
+ *
+ ************************************************************************************/
+
+#ifdef HAVE_16BIT_TIMERS
+static int stm32_interrupt(FAR struct stm32_lowerhalf_s *priv)
+{
+ uint16_t regval;
+
+ /* Verify that this is an update interrupt. Nothing else is expected. */
+
+ regval = stm32_getreg16(priv, STM32_GTIM_SR_OFFSET);
+ DEBUGASSERT((regval & ATIM_SR_UIF) != 0);
+
+ /* Clear the UIF interrupt bit */
+
+ stm32_putreg16(priv, STM32_GTIM_SR_OFFSET, regval & ~GTIM_SR_UIF);
+
+ /* Check the direction bit in the CR1 register and add or subtract the
+ * maximum value, as appropriate.
+ */
+
+ regval = stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET);
+ if ((regval & ATIM_CR1_DIR) != 0)
+ {
+ priv->position -= (int32_t)0x0000ffff;
+ }
+ else
+ {
+ priv->position += (int32_t)0x0000ffff;
+ }
+
+ return OK;
+}
+#endif
+
+/************************************************************************************
+ * Name: stm32_intNinterrupt
+ *
+ * Description:
+ * TIMN interrupt handler
+ *
+ ************************************************************************************/
+
+#if defined(CONFIG_STM32_TIM1_QE) && TIM1_BITWIDTH == 16
+static int stm32_tim1interrupt(int irq, FAR void *context)
+{
+ return stm32_interrupt(&g_tim1lower);
+}
+#endif
+
+#if defined(CONFIG_STM32_TIM2_QE) && TIM2_BITWIDTH == 16
+static int stm32_tim2interrupt(int irq, FAR void *context)
+{
+ return stm32_interrupt(&g_tim2lower);
+}
+#endif
+
+#if defined(CONFIG_STM32_TIM3_QE) && TIM3_BITWIDTH == 16
+static int stm32_tim3interrupt(int irq, FAR void *context)
+{
+ return stm32_interrupt(&g_tim3lower);
+}
+#endif
+
+#if defined(CONFIG_STM32_TIM4_QE) && TIM4_BITWIDTH == 16
+static int stm32_tim4interrupt(int irq, FAR void *context)
+{
+ return stm32_interrupt(&g_tim4lower);
+}
+#endif
+
+#if defined(CONFIG_STM32_TIM5_QE) && TIM5_BITWIDTH == 16
+static int stm32_tim5interrupt(int irq, FAR void *context)
+{
+ return stm32_interrupt(&g_tim5lower);
+}
+#endif
+
+#if defined(CONFIG_STM32_TIM8_QE) && TIM8_BITWIDTH == 16
+static int stm32_tim8interrupt(int irq, FAR void *context)
+{
+ return stm32_interrupt(&g_tim8lower);
+}
+#endif
+
+/************************************************************************************
+ * Name: stm32_setup
+ *
+ * Description:
+ * This method is called when the driver is opened. The lower half driver
+ * should configure and initialize the device so that it is ready for use.
+ * The initial position value should be zero. *
+ *
+ ************************************************************************************/
+
+static int stm32_setup(FAR struct qe_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ uint16_t dier;
+ uint16_t smcr;
+ uint16_t ccmr1;
+ uint16_t ccer;
+ uint16_t cr1;
+#ifdef HAVE_16BIT_TIMERS
+ uint16_t regval;
+ int ret;
+#endif
+
+ /* NOTE: Clocking should have been enabled in the low-level RCC logic at boot-up */
+
+ /* Timer base configuration */
+
+ cr1 = stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET);
+
+ /* Clear the direction bit (0=count up) and select the Counter Mode (0=Edge aligned)
+ * (Timers 2-5 and 1-8 only)
+ */
+
+ cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK);
+ stm32_putreg16(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+ /* Set the Autoreload value */
+
+#if defined(HAVE_MIXEDWIDTH_TIMERS)
+ if (priv->config->width == 32)
+ {
+ stm32_putreg32(priv, STM32_GTIM_ARR_OFFSET, 0xffffffff);
+ }
+ else
+ {
+ stm32_putreg32(priv, STM32_GTIM_ARR_OFFSET, 0xffff);
+ }
+#elif defined(HAVE_32BIT_TIMERS)
+ stm32_putreg32(priv, STM32_GTIM_ARR_OFFSET, 0xffffffff);
+#else
+ stm32_putreg32(priv, STM32_GTIM_ARR_OFFSET, 0xffff);
+#endif
+
+ /* Set the timerp rescaler value. The clock input value (CLKIN) is based on the
+ * peripheral clock (PCLK) and a multiplier. These CLKIN values are provided in
+ * the board.h file. The prescaler value is then that CLKIN value divided by the
+ * configured CLKOUT value (minus one)
+ */
+
+ stm32_putreg16(priv, STM32_GTIM_PSC_OFFSET, (uint16_t)priv->config->psc);
+
+#if defined(CONFIG_STM32_TIM1_QE) || defined(CONFIG_STM32_TIM8_QE)
+ if (priv->config->timid == 1 || priv->config->timid == 8)
+ {
+ /* Clear the Repetition Counter value */
+
+ stm32_putreg16(priv, STM32_ATIM_RCR_OFFSET, 0);
+ }
+#endif
+
+ /* Generate an update event to reload the Prescaler
+ * and the repetition counter(only for TIM1 and TIM8) value immediatly
+ */
+
+ stm32_putreg16(priv, STM32_GTIM_EGR_OFFSET, GTIM_EGR_UG);
+
+ /* GPIO pin configuration */
+
+ stm32_configgpio(priv->config->ti1cfg);
+ stm32_configgpio(priv->config->ti2cfg);
+
+ /* Set the encoder Mode 3 */
+
+ smcr = stm32_getreg16(priv, STM32_GTIM_SMCR_OFFSET);
+ smcr &= ~GTIM_SMCR_SMS_MASK;
+ smcr |= GTIM_SMCR_ENCMD3;
+ stm32_putreg16(priv, STM32_GTIM_SMCR_OFFSET, smcr);
+
+ /* TI1 Channel Configuration */
+ /* Disable the Channel 1: Reset the CC1E Bit */
+
+ ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET);
+ ccer &= ~GTIM_CCER_CC1E;
+ stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer);
+
+ ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET);
+ ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET);
+
+ /* Select the Input IC1=TI1 and set the filter fSAMPLING=fDTS/4, N=6 */
+
+ ccmr1 &= ~(GTIM_CCMR1_CC1S_MASK|GTIM_CCMR1_IC1F_MASK);
+ ccmr1 |= GTIM_CCMR_CCS_CCIN1 << GTIM_CCMR1_CC1S_SHIFT;
+ ccmr1 |= GTIM_CCMR_ICF_FDTSd46 << GTIM_CCMR1_IC1F_SHIFT;
+
+ /* Select the Polarity=rising and set the CC1E Bit */
+
+ ccer &= ~(GTIM_CCER_CC1P | GTIM_CCER_CC1NP);
+ ccer |= GTIM_CCER_CC1E;
+
+ /* Write to TIM CCMR1 and CCER registers */
+
+ stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
+ stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer);
+
+ /* Set the Input Capture Prescaler value: Capture performed each time an
+ * edge is detected on the capture input.
+ */
+
+ ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET);
+ ccmr1 &= ~GTIM_CCMR1_IC1PSC_MASK;
+ ccmr1 |= (GTIM_CCMR_ICPSC_NOPSC << GTIM_CCMR1_IC1PSC_SHIFT);
+ stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
+
+ /* TI2 Channel Configuration */
+ /* Disable the Channel 2: Reset the CC2E Bit */
+
+ ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET);
+ ccer &= ~GTIM_CCER_CC2E;
+ stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer);
+
+ ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET);
+ ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET);
+
+ /* Select the Input IC2=TI2 and set the filter fSAMPLING=fDTS/4, N=6 */
+
+ ccmr1 &= ~(GTIM_CCMR1_CC2S_MASK|GTIM_CCMR1_IC2F_MASK);
+ ccmr1 |= GTIM_CCMR_CCS_CCIN1 << GTIM_CCMR1_CC2S_SHIFT;
+ ccmr1 |= GTIM_CCMR_ICF_FDTSd46 << GTIM_CCMR1_IC2F_SHIFT;
+
+ /* Select the Polarity=rising and set the CC2E Bit */
+
+ ccer &= ~(GTIM_CCER_CC2P | GTIM_CCER_CC2NP);
+ ccer |= GTIM_CCER_CC2E;
+
+ /* Write to TIM CCMR1 and CCER registers */
+
+ stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
+ stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer);
+
+ /* Set the Input Capture Prescaler value: Capture performed each time an
+ * edge is detected on the capture input.
+ */
+
+ ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET);
+ ccmr1 &= ~GTIM_CCMR1_IC2PSC_MASK;
+ ccmr1 |= (GTIM_CCMR_ICPSC_NOPSC << GTIM_CCMR1_IC2PSC_SHIFT);
+ stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
+
+ /* Disable the update interrupt */
+
+ dier = stm32_getreg16(priv, STM32_GTIM_DIER_OFFSET);
+ dier &= ~GTIM_DIER_UIE;
+ stm32_putreg16(priv, STM32_GTIM_DIER_OFFSET, dier);
+
+ /* There is no need for interrupts with 32-bit timers */
+
+#ifdef HAVE_16BIT_TIMERS
+#ifdef HAVE_MIXEDWIDTH_TIMERS
+ if (priv->config->width != 32)
+#endif
+ {
+ /* Attach the interrupt handler */
+
+ ret = irq_attach(priv->config->irq, priv->config->handler);
+ if (ret < 0)
+ {
+ stm32_shutdown(lower);
+ return ret;
+ }
+
+ /* Enable the update/global interrupt at the NVIC */
+
+ up_enable_irq(priv->config->irq);
+ }
+#endif
+
+ /* Reset the Update Disable Bit */
+
+ cr1 = stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET);
+ cr1 &= ~GTIM_CR1_UDIS;
+ stm32_putreg16(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+ /* Reset the URS Bit */
+
+ cr1 &= ~GTIM_CR1_URS;
+ stm32_putreg16(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+ /* There is no need for interrupts with 32-bit timers */
+
+#ifdef HAVE_16BIT_TIMERS
+#ifdef HAVE_MIXEDWIDTH_TIMERS
+ if (priv->config->width != 32)
+#endif
+ {
+ /* Clear any pending update interrupts */
+
+ regval = stm32_getreg16(priv, STM32_GTIM_SR_OFFSET);
+ stm32_putreg16(priv, STM32_GTIM_SR_OFFSET, regval & ~GTIM_SR_UIF);
+
+ /* Then enable the update interrupt */
+
+ dier = stm32_getreg16(priv, STM32_GTIM_DIER_OFFSET);
+ dier |= GTIM_DIER_UIE;
+ stm32_putreg16(priv, STM32_GTIM_DIER_OFFSET, dier);
+ }
+#endif
+
+ /* Enable the TIM Counter */
+
+ cr1 = stm32_getreg16(priv, STM32_GTIM_CR1_OFFSET);
+ cr1 |= GTIM_CR1_CEN;
+ stm32_putreg16(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+ return OK;
+}
+
+/************************************************************************************
+ * Name: stm32_shutdown
+ *
+ * Description:
+ * This method is called when the driver is closed. The lower half driver
+ * should stop data collection, free any resources, disable timer hardware, and
+ * put the system into the lowest possible power usage state *
+ *
+ ************************************************************************************/
+
+static int stm32_shutdown(FAR struct qe_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ irqstate_t flags;
+ uint32_t regaddr;
+ uint32_t regval;
+ uint32_t resetbit;
+ uint32_t pincfg;
+
+ /* Disable the update/global interrupt at the NVIC */
+
+ flags = irqsave();
+ up_disable_irq(priv->config->irq);
+
+ /* Detach the interrupt handler */
+
+ (void)irq_detach(priv->config->irq);
+
+ /* Disable interrupts momentary to stop any ongoing timer processing and
+ * to prevent any concurrent access to the reset register.
+ */
+
+ /* Disable further interrupts and stop the timer */
+
+ stm32_putreg16(priv, STM32_GTIM_DIER_OFFSET, 0);
+ stm32_putreg16(priv, STM32_GTIM_SR_OFFSET, 0);
+
+ /* Determine which timer to reset */
+
+ switch (priv->config->timid)
+ {
+#ifdef CONFIG_STM32_TIM1_PWM
+ case 1:
+ regaddr = STM32_RCC_APB2RSTR;
+ resetbit = RCC_APB2RSTR_TIM1RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM2_PWM
+ case 2:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM2RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM3_PWM
+ case 3:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM3RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM4_PWM
+ case 4:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM4RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM5_PWM
+ case 5:
+ regaddr = STM32_RCC_APB1RSTR;
+ resetbit = RCC_APB1RSTR_TIM5RST;
+ break;
+#endif
+#ifdef CONFIG_STM32_TIM8_PWM
+ case 8:
+ regaddr = STM32_RCC_APB2RSTR;
+ resetbit = RCC_APB2RSTR_TIM8RST;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ /* Reset the timer - stopping the output and putting the timer back
+ * into a state where stm32_start() can be called.
+ */
+
+ regval = getreg32(regaddr);
+ regval |= resetbit;
+ putreg32(regval, regaddr);
+
+ regval &= ~resetbit;
+ putreg32(regval, regaddr);
+ irqrestore(flags);
+
+ qevdbg("regaddr: %08x resetbit: %08x\n", regaddr, resetbit);
+ stm32_dumpregs(priv, "After stop");
+
+ /* Put the TI1 GPIO pin back to its default state */
+
+ pincfg = priv->config->ti1cfg & (GPIO_PORT_MASK|GPIO_PIN_MASK);
+
+#if defined(CONFIG_STM32_STM32F10XX)
+ pincfg |= (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT);
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ pincfg |= (GPIO_INPUT|GPIO_FLOAT);
+#else
+# error "Unrecognized STM32 chip"
+#endif
+
+ stm32_configgpio(pincfg);
+
+ /* Put the TI2 GPIO pin back to its default state */
+
+ pincfg = priv->config->ti2cfg & (GPIO_PORT_MASK|GPIO_PIN_MASK);
+
+#if defined(CONFIG_STM32_STM32F10XX)
+ pincfg |= (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT);
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ pincfg |= (GPIO_INPUT|GPIO_FLOAT);
+#else
+# error "Unrecognized STM32 chip"
+#endif
+
+ stm32_configgpio(pincfg);
+ return -ENOSYS;
+}
+
+/************************************************************************************
+ * Name: stm32_position
+ *
+ * Description:
+ * Return the current position measurement.
+ *
+ ************************************************************************************/
+
+static int stm32_position(FAR struct qe_lowerhalf_s *lower, int32_t *pos)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+#ifdef HAVE_16BIT_TIMERS
+ int32_t position;
+ int32_t verify;
+ uint32_t count;
+
+ DEBUGASSERT(lower && priv->inuse);
+
+ /* Loop until we are certain that no interrupt occurred between samples */
+
+ do
+ {
+ /* Don't let another task pre-empt us until we get the measurement. The timer
+ * interrupt may still be processed
+ */
+
+ sched_lock();
+ position = priv->position;
+ count = stm32_getreg32(priv, STM32_GTIM_CNT_OFFSET);
+ verify = priv->position;
+ sched_unlock();
+ }
+ while (position != verify);
+
+ /* Return the position measurement */
+
+ *pos = position + (int32_t)count;
+#else
+ /* Return the counter value */
+
+ *pos = (int32_t)stm32_getreg32(priv, STM32_GTIM_CNT_OFFSET);;
+#endif
+ return OK;
+}
+
+/************************************************************************************
+ * Name: stm32_reset
+ *
+ * Description:
+ * Reset the position measurement to zero.
+ *
+ ************************************************************************************/
+
+static int stm32_reset(FAR struct qe_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+#ifdef HAVE_16BIT_TIMERS
+ irqstate_t flags;
+
+ qevdbg("Resetting position to zero\n");
+ DEBUGASSERT(lower && priv->inuse);
+
+ /* Reset the timer and the counter. Interrupts are disabled to make this atomic
+ * (if possible)
+ */
+
+ flags = irqsave();
+ stm32_putreg32(priv, STM32_GTIM_CNT_OFFSET, 0);
+ priv->position = 0;
+ irqrestore(flags);
+#else
+ qevdbg("Resetting position to zero\n");
+ DEBUGASSERT(lower && priv->inuse);
+
+ /* Reset the counter to zero */
+
+ stm32_putreg32(priv, STM32_GTIM_CNT_OFFSET, 0);
+#endif
+ return OK;
+}
+
+/************************************************************************************
+ * Name: stm32_ioctl
+ *
+ * Description:
+ * Lower-half logic may support platform-specific ioctl commands
+ *
+ ************************************************************************************/
+
+static int stm32_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, unsigned long arg)
+{
+ /* No ioctl commands supported */
+
+ return -ENOTTY;
+}
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_qeinitialize
+ *
+ * Description:
+ * Initialize a quadrature encoder interface. This function must be called from
+ * board-specific logic.
+ *
+ * Input Parameters:
+ * devpath - The full path to the driver to register. E.g., "/dev/qe0"
+ * tim - The timer number to used. 'tim' must be an element of {1,2,3,4,5,8}
+ *
+ * Returned Values:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ************************************************************************************/
+
+int stm32_qeinitialize(FAR const char *devpath, int tim)
+{
+ FAR struct stm32_lowerhalf_s *priv;
+ int ret;
+
+ /* Find the pre-allocated timer state structure corresponding to this timer */
+
+ priv = stm32_tim2lower(tim);
+ if (!priv)
+ {
+ qedbg("TIM%d support not configured\n", tim);
+ return -ENXIO;
+ }
+
+ /* Make sure that it is available */
+
+ if (priv->inuse)
+ {
+ qedbg("TIM%d is in-used\n", tim);
+ return -EBUSY;
+ }
+
+ /* Register the priv-half driver */
+
+ ret = qe_register(devpath, (FAR struct qe_lowerhalf_s *)priv);
+ if (ret < 0)
+ {
+ qedbg("qe_register failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Make sure that the timer is in the shutdown state */
+
+ stm32_shutdown((FAR struct qe_lowerhalf_s *)priv);
+
+ /* The driver is now in-use */
+
+ priv->inuse = true;
+ return OK;
+}
+
+#endif /* CONFIG_QENCODER */
diff --git a/nuttx/arch/arm/src/stm32/stm32_qencoder.h b/nuttx/arch/arm/src/stm32/stm32_qencoder.h
new file mode 100644
index 000000000..5effa7163
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_qencoder.h
@@ -0,0 +1,142 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_qencoder.h
+ *
+ * Copyright (C) 2012 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_STM32_STM32_QENCODER_H
+#define __ARCH_ARM_SRC_STM32_STM32_QENCODER_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+#ifdef CONFIG_QENCODER
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+/* Timer devices may be used for different purposes. One special purpose is as
+ * a quadrature encoder input device. If CONFIG_STM32_TIMn is defined then the
+ * CONFIG_STM32_TIMn_QE must also be defined to indicate that timer "n" is intended
+ * to be used for as a quadrature encoder.
+ */
+
+#ifndef CONFIG_STM32_TIM1
+# undef CONFIG_STM32_TIM1_QE
+#endif
+#ifndef CONFIG_STM32_TIM2
+# undef CONFIG_STM32_TIM2_QE
+#endif
+#ifndef CONFIG_STM32_TIM3
+# undef CONFIG_STM32_TIM3_QE
+#endif
+#ifndef CONFIG_STM32_TIM4
+# undef CONFIG_STM32_TIM4_QE
+#endif
+#ifndef CONFIG_STM32_TIM5
+# undef CONFIG_STM32_TIM5_QE
+#endif
+#ifndef CONFIG_STM32_TIM8
+# undef CONFIG_STM32_TIM8_QE
+#endif
+
+/* Only timers 2-5, and 1 & 8 can be used as a quadrature encoder (at least for the
+ * STM32 F4)
+ */
+
+#undef CONFIG_STM32_TIM6_QE
+#undef CONFIG_STM32_TIM7_QE
+#undef CONFIG_STM32_TIM9_QE
+#undef CONFIG_STM32_TIM10_QE
+#undef CONFIG_STM32_TIM11_QE
+#undef CONFIG_STM32_TIM12_QE
+#undef CONFIG_STM32_TIM13_QE
+#undef CONFIG_STM32_TIM14_QE
+
+/* Clock out frequency. This value is used to calculation the timer CLKIN in
+ * prescaler value.
+ */
+
+#ifndef CONFIG_STM32_TIM1_QECLKOUT
+# define CONFIG_STM32_TIM1_QECLKOUT 28000000
+#endif
+
+#ifndef CONFIG_STM32_TIM2_QECLKOUT
+# define CONFIG_STM32_TIM2_QECLKOUT 28000000
+#endif
+
+#ifndef CONFIG_STM32_TIM3_QECLKOUT
+# define CONFIG_STM32_TIM3_QECLKOUT 28000000
+#endif
+
+#ifndef CONFIG_STM32_TIM4_QECLKOUT
+# define CONFIG_STM32_TIM4_QECLKOUT 28000000
+#endif
+
+#ifndef CONFIG_STM32_TIM5_QECLKOUT
+# define CONFIG_STM32_TIM5_QECLKOUT 28000000
+#endif
+
+#ifndef CONFIG_STM32_TIM8_QECLKOUT
+# define CONFIG_STM32_TIM8_QECLKOUT 28000000
+#endif
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_qeinitialize
+ *
+ * Description:
+ * Initialize a quadrature encoder interface. This function must be called from
+ * board-specific logic..
+ *
+ * Input Parameters:
+ * devpath - The full path to the driver to register. E.g., "/dev/qe0"
+ * tim - The timer number to used. 'tim' must be an element of {1,2,3,4,5,8}
+ *
+ * Returned Values:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ************************************************************************************/
+
+int stm32_qeinitialize(FAR const char *devpath, int tim);
+
+#endif /* CONFIG_QENCODER */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_QENCODER_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_rcc.c b/nuttx/arch/arm/src/stm32/stm32_rcc.c
new file mode 100644
index 000000000..6656186f2
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_rcc.c
@@ -0,0 +1,183 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_rcc.c
+ *
+ * Copyright (C) 2009, 2011-2012 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 <stdio.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "chip.h"
+#include "stm32_rcc.h"
+#include "stm32_flash.h"
+#include "stm32_internal.h"
+#include "stm32_waste.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* Allow up to 100 milliseconds for the high speed clock to become ready.
+ * that is a very long delay, but if the clock does not become ready we are
+ * hosed anyway.
+ */
+
+#define HSERDY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Include chip-specific clocking initialization logic */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "chip/stm32f10xxx_rcc.c"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/stm32f20xxx_rcc.c"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32f40xxx_rcc.c"
+#else
+# error "Unsupported STM32 chip"
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_clockconfig
+ *
+ * Description:
+ * Called to establish the clock settings based on the values in board.h. This
+ * function (by default) will reset most everything, enable the PLL, and enable
+ * peripheral clocking for all periperipherals enabled in the NuttX configuration
+ * file.
+ *
+ * If CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG is defined, then clocking will
+ * be enabled by an externally provided, board-specific function called
+ * stm32_board_clockconfig().
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+void stm32_clockconfig(void)
+{
+ /* Make sure that we are starting in the reset state */
+
+ rcc_reset();
+
+#if defined(CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG)
+
+ /* Invoke Board Custom Clock Configuration */
+
+ stm32_board_clockconfig();
+
+#else
+
+ /* Invoke standard, fixed clock configuration based on definitions in board.h */
+
+ stm32_stdclockconfig();
+
+#endif
+
+ /* Enable peripheral clocking */
+
+ rcc_enableperipherals();
+}
+
+/************************************************************************************
+ * Name: stm32_clockenable
+ *
+ * Description:
+ * Re-enable the clock and restore the clock settings based on settings in board.h.
+ * This function is only available to support low-power modes of operation: When
+ * re-awakening from deep-sleep modes, it is necessary to re-enable/re-start the
+ * PLL
+ *
+ * This functional performs a subset of the operations performed by
+ * stm32_clockconfig(): It does not reset any devices, and it does not reset the
+ * currenlty enabled peripheral clocks.
+ *
+ * If CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG is defined, then clocking will
+ * be enabled by an externally provided, board-specific function called
+ * stm32_board_clockconfig().
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_PM
+void stm32_clockenable(void)
+{
+#if defined(CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG)
+
+ /* Invoke Board Custom Clock Configuration */
+
+ stm32_board_clockconfig();
+
+#else
+
+ /* Invoke standard, fixed clock configuration based on definitions in board.h */
+
+ stm32_stdclockconfig();
+
+#endif
+}
+#endif
+
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_rcc.h b/nuttx/arch/arm/src/stm32/stm32_rcc.h
new file mode 100644
index 000000000..c4d43db3a
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_rcc.h
@@ -0,0 +1,239 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_rcc.h
+ *
+ * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.orgr>
+ *
+ * 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_STM32_STM32_RRC_H
+#define __ARCH_ARM_SRC_STM32_STM32_RRC_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "up_arch.h"
+#include "chip.h"
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "chip/stm32f10xxx_rcc.h"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/stm32f20xxx_rcc.h"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32f40xxx_rcc.h"
+#endif
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/* This symbol references the Cortex-M3 vector table (as positioned by the the linker
+ * script, ld.script or ld.script.dfu. The standard location for the vector table is
+ * at the beginning of FLASH at address 0x0800:0000. If we are using the STMicro DFU
+ * bootloader, then the vector table will be offset to a different location in FLASH
+ * and we will need to set the NVIC vector location to this alternative location.
+ */
+
+extern uint32_t stm32_vectors[]; /* See stm32_vectors.S */
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_mco1config
+ *
+ * Description:
+ * Selects the clock source to output on MCO1 pin (PA8). PA8 should be configured in
+ * alternate function mode.
+ *
+ * Input Parameters:
+ * source - One of the definitions for the RCC_CFGR_MCO1 definitions from
+ * chip/stm32f40xxx_rcc.h {RCC_CFGR_MCO1_HSI, RCC_CFGR_MCO1_LSE,
+ * RCC_CFGR_MCO1_HSE, RCC_CFGR_MCO1_PLL}
+ * div - One of the definitions for the RCC_CFGR_MCO1PRE definitions from
+ * chip/stm32f40xxx_rcc.h {RCC_CFGR_MCO1PRE_NONE, RCC_CFGR_MCO1PRE_DIV2,
+ * RCC_CFGR_MCO1PRE_DIV3, RCC_CFGR_MCO1PRE_DIV4, RCC_CFGR_MCO1PRE_DIV5}
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+static inline void stm32_mco1config(uint32_t source, uint32_t div)
+{
+ uint32_t regval;
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~(RCC_CFGR_MCO1_MASK|RCC_CFGR_MCO1PRE_MASK);
+ regval |= (source | div);
+ putreg32(regval, STM32_RCC_CFGR);
+}
+#endif
+
+/************************************************************************************
+ * Name: stm32_mco2config
+ *
+ * Description:
+ * Selects the clock source to output on MCO2 pin (PC9). PC9 should be configured in
+ * alternate function mode.
+ *
+ * Input Parameters:
+ * source - One of the definitions for the RCC_CFGR_MCO2 definitions from
+ * chip/stm32f40xxx_rcc.h {RCC_CFGR_MCO2_SYSCLK, RCC_CFGR_MCO2_PLLI2S,
+ * RCC_CFGR_MCO2_HSE, RCC_CFGR_MCO2_PLL}
+ * div - One of the definitions for the RCC_CFGR_MCO2PRE definitions from
+ * chip/stm32f40xxx_rcc.h {RCC_CFGR_MCO2PRE_NONE, RCC_CFGR_MCO2PRE_DIV2,
+ * RCC_CFGR_MCO2PRE_DIV3, RCC_CFGR_MCO2PRE_DIV4, RCC_CFGR_MCO2PRE_DIV5}
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+static inline void stm32_mco2config(uint32_t source, uint32_t div)
+{
+ uint32_t regval;
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~(RCC_CFGR_MCO2_MASK|RCC_CFGR_MCO2PRE_MASK);
+ regval |= (source | div);
+ putreg32(regval, STM32_RCC_CFGR);
+}
+#endif
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_clockconfig
+ *
+ * Description:
+ * Called to establish the clock settings based on the values in board.h. This
+ * function (by default) will reset most everything, enable the PLL, and enable
+ * peripheral clocking for all periperipherals enabled in the NuttX configuration
+ * file.
+ *
+ * If CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG is defined, then clocking will
+ * be enabled by an externally provided, board-specific function called
+ * stm32_board_clockconfig().
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+EXTERN void stm32_clockconfig(void);
+
+/************************************************************************************
+ * Name: stm32_clockenable
+ *
+ * Description:
+ * Re-enable the clock and restore the clock settings based on settings in board.h.
+ * This function is only available to support low-power modes of operation: When
+ * re-awakening from deep-sleep modes, it is necessary to re-enable/re-start the
+ * PLL
+ *
+ * This functional performs a subset of the operations performed by
+ * stm32_clockconfig(): It does not reset any devices, and it does not reset the
+ * currenlty enabled peripheral clocks.
+ *
+ * If CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG is defined, then clocking will
+ * be enabled by an externally provided, board-specific function called
+ * stm32_board_clockconfig().
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_PM
+EXTERN void stm32_clockenable(void);
+#endif
+
+/************************************************************************************
+ * Name: stm32_rcc_enablelse
+ *
+ * Description:
+ * Enable the External Low-Speed (LSE) Oscillator and, if the RTC is
+ * configured, setup the LSE as the RTC clock source, and enable the RTC.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+EXTERN void stm32_rcc_enablelse(void);
+
+/****************************************************************************
+ * Name: stm32_rcc_enablelsi
+ *
+ * Description:
+ * Enable the Internal Low-Speed (LSI) RC Oscillator.
+ *
+ ****************************************************************************/
+
+EXTERN void stm32_rcc_enablelsi(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_RRC_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_rtc.c b/nuttx/arch/arm/src/stm32/stm32_rtc.c
new file mode 100644
index 000000000..b79a74dcb
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_rtc.c
@@ -0,0 +1,80 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_rtc.c
+ *
+ * Copyright (C) 2011 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 "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* This file is only a thin shell that includes the correct RTC implementation
+ * for the selected STM32 family. The correct file cannot be selected by
+ * the make system because it needs the intelligence that only exists in
+ * chip.h that can associate an STM32 part number with an STM32 family.
+ *
+ * The STM32 F4 RTC differs dramatically the F1 RTC. The F1 RTC is a simple
+ * battery-backed counter; the F4 RTC is provides broken-out data/time in BCD
+ * format.
+ */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "stm32f10xxx_rtc.c"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "stm32f20xxx_rtc.c"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "stm32f40xxx_rtc.c"
+#endif
diff --git a/nuttx/arch/arm/src/stm32/stm32_rtc.h b/nuttx/arch/arm/src/stm32/stm32_rtc.h
new file mode 100644
index 000000000..11822f76c
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_rtc.h
@@ -0,0 +1,85 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_rtc.h
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_STM32_STM32_RTC_H
+#define __ARCH_ARM_SRC_STM32_STM32_RTC_H
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "chip/stm32f10xxx_rtc.h"
+# include "chip/stm32_bkp.h"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/stm32f20xxx_rtc.h"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32f40xxx_rtc.h"
+#endif
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#define STM32_RTC_PRESCALER_SECOND 32767 /* Default prescaler to get a second base */
+#define STM32_RTC_PRESCALER_MIN 1 /* Maximum speed of 16384 Hz */
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/* Set alarm output pin */
+
+EXTERN void stm32_rtc_settalarmpin(bool activate);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_RTC_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_sdio.c b/nuttx/arch/arm/src/stm32/stm32_sdio.c
new file mode 100644
index 000000000..b109160a1
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_sdio.c
@@ -0,0 +1,2842 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_sdio.c
+ *
+ * Copyright (C) 2009, 2011-2012 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 <stdbool.h>
+#include <semaphore.h>
+#include <string.h>
+#include <assert.h>
+#include <debug.h>
+#include <wdog.h>
+#include <errno.h>
+
+#include <nuttx/clock.h>
+#include <nuttx/arch.h>
+#include <nuttx/sdio.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/mmcsd.h>
+
+#include <arch/irq.h>
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "up_arch.h"
+
+#include "stm32_internal.h"
+#include "stm32_dma.h"
+#include "stm32_sdio.h"
+
+#if CONFIG_STM32_SDIO
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+/* Required system configuration options:
+ *
+ * CONFIG_ARCH_DMA - Enable architecture-specific DMA subsystem
+ * initialization. Required if CONFIG_SDIO_DMA is enabled.
+ * CONFIG_STM32_DMA2 - Enable STM32 DMA2 support. Required if
+ * CONFIG_SDIO_DMA is enabled
+ * CONFIG_SCHED_WORKQUEUE -- Callback support requires work queue support.
+ *
+ * Driver-specific configuration options:
+ *
+ * CONFIG_SDIO_MUXBUS - Setting this configuration enables some locking
+ * APIs to manage concurrent accesses on the SDIO bus. This is not
+ * needed for the simple case of a single SD card, for example.
+ * CONFIG_SDIO_DMA - Enable SDIO. This is a marginally optional. For
+ * most usages, SDIO will cause data overruns if used without DMA.
+ * NOTE the above system DMA configuration options.
+ * CONFIG_SDIO_WIDTH_D1_ONLY - This may be selected to force the driver
+ * operate with only a single data line (the default is to use all
+ * 4 SD data lines).
+ * CONFIG_SDIO_PRI - SDIO interrupt priority. This setting is not very
+ * important since interrupt nesting is not currently supported.
+ * CONFIG_SDM_DMAPRIO - SDIO DMA priority. This can be selecte if
+ * CONFIG_SDIO_DMA is enabled.
+ * CONFIG_SDIO_XFRDEBUG - Enables some very low-level debug output
+ * This also requires CONFIG_DEBUG_FS and CONFIG_DEBUG_VERBOSE
+ */
+
+#if defined(CONFIG_SDIO_DMA) && !defined(CONFIG_STM32_DMA2)
+# warning "CONFIG_SDIO_DMA support requires CONFIG_STM32_DMA2"
+#endif
+
+#ifndef CONFIG_SDIO_DMA
+# warning "Large Non-DMA transfer may result in RX overrun failures"
+#endif
+
+#ifndef CONFIG_SCHED_WORKQUEUE
+# error "Callback support requires CONFIG_SCHED_WORKQUEUE"
+#endif
+
+#ifndef CONFIG_SDIO_PRI
+# define CONFIG_SDIO_PRI NVIC_SYSH_PRIORITY_DEFAULT
+#endif
+
+#ifdef CONFIG_SDIO_DMA
+# ifndef CONFIG_SDIO_DMAPRIO
+# if defined(CONFIG_STM32_STM32F10XX)
+# define CONFIG_SDIO_DMAPRIO DMA_CCR_PRIMED
+# elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define CONFIG_SDIO_DMAPRIO DMA_SCR_PRIVERYHI
+# else
+# error "Unknown STM32 DMA"
+# endif
+# endif
+# if defined(CONFIG_STM32_STM32F10XX)
+# if (CONFIG_SDIO_DMAPRIO & ~DMA_CCR_PL_MASK) != 0
+# error "Illegal value for CONFIG_SDIO_DMAPRIO"
+# endif
+# elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# if (CONFIG_SDIO_DMAPRIO & ~DMA_SCR_PL_MASK) != 0
+# error "Illegal value for CONFIG_SDIO_DMAPRIO"
+# endif
+# else
+# error "Unknown STM32 DMA"
+# endif
+#else
+# undef CONFIG_SDIO_DMAPRIO
+#endif
+
+#if !defined(CONFIG_DEBUG_FS) || !defined(CONFIG_DEBUG)
+# undef CONFIG_SDIO_XFRDEBUG
+#endif
+
+/* Friendly CLKCR bit re-definitions ****************************************/
+
+#define SDIO_CLKCR_RISINGEDGE (0)
+#define SDIO_CLKCR_FALLINGEDGE SDIO_CLKCR_NEGEDGE
+
+/* Mode dependent settings. These depend on clock devisor settings that must
+ * be defined in the board-specific board.h header file: SDIO_INIT_CLKDIV,
+ * SDIO_MMCXFR_CLKDIV, and SDIO_SDXFR_CLKDIV.
+ */
+
+#define STM32_CLCKCR_INIT (SDIO_INIT_CLKDIV|SDIO_CLKCR_RISINGEDGE|\
+ SDIO_CLKCR_WIDBUS_D1)
+#define SDIO_CLKCR_MMCXFR (SDIO_MMCXFR_CLKDIV|SDIO_CLKCR_RISINGEDGE|\
+ SDIO_CLKCR_WIDBUS_D1)
+#define SDIO_CLCKR_SDXFR (SDIO_SDXFR_CLKDIV|SDIO_CLKCR_RISINGEDGE|\
+ SDIO_CLKCR_WIDBUS_D1)
+#define SDIO_CLCKR_SDWIDEXFR (SDIO_SDXFR_CLKDIV|SDIO_CLKCR_RISINGEDGE|\
+ SDIO_CLKCR_WIDBUS_D4)
+
+/* Timing */
+
+#define SDIO_CMDTIMEOUT (100000)
+#define SDIO_LONGTIMEOUT (0x7fffffff)
+
+/* Big DTIMER setting */
+
+#define SDIO_DTIMER_DATATIMEOUT (0x000fffff)
+
+/* DMA channel/stream configuration register settings. The following
+ * must be selected. The DMA driver will select the remaining fields.
+ *
+ * - 32-bit DMA
+ * - Memory increment
+ * - Direction (memory-to-peripheral, peripheral-to-memory)
+ * - Memory burst size (F4 only)
+ */
+
+/* STM32 F1 channel configuration register (CCR) settings */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# define SDIO_RXDMA32_CONFIG (CONFIG_SDIO_DMAPRIO|DMA_CCR_MSIZE_32BITS|\
+ DMA_CCR_PSIZE_32BITS|DMA_CCR_MINC)
+# define SDIO_TXDMA32_CONFIG (CONFIG_SDIO_DMAPRIO|DMA_CCR_MSIZE_32BITS|\
+ DMA_CCR_PSIZE_32BITS|DMA_CCR_MINC|DMA_CCR_DIR)
+
+/* STM32 F4 stream configuration register (SCR) settings. */
+
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define SDIO_RXDMA32_CONFIG (DMA_SCR_PFCTRL|DMA_SCR_DIR_P2M|DMA_SCR_MINC|\
+ DMA_SCR_PSIZE_32BITS|DMA_SCR_MSIZE_32BITS|\
+ CONFIG_SDIO_DMAPRIO|DMA_SCR_PBURST_INCR4|\
+ DMA_SCR_MBURST_INCR4)
+# define SDIO_TXDMA32_CONFIG (DMA_SCR_PFCTRL|DMA_SCR_DIR_M2P|DMA_SCR_MINC|\
+ DMA_SCR_PSIZE_32BITS|DMA_SCR_MSIZE_32BITS|\
+ CONFIG_SDIO_DMAPRIO|DMA_SCR_PBURST_INCR4|\
+ DMA_SCR_MBURST_INCR4)
+#else
+# error "Unknown STM32 DMA"
+#endif
+
+/* SDIO DMA Channel/Stream selection. For the the case of the STM32 F4, there
+ * are multiple DMA stream options that must be dis-ambiguated in the board.h
+ * file.
+ */
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# define SDIO_DMACHAN DMACHAN_SDIO
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define SDIO_DMACHAN DMAMAP_SDIO
+#else
+# error "Unknown STM32 DMA"
+#endif
+
+/* FIFO sizes */
+
+#define SDIO_HALFFIFO_WORDS (8)
+#define SDIO_HALFFIFO_BYTES (8*4)
+
+/* Data transfer interrupt mask bits */
+
+#define SDIO_RECV_MASK (SDIO_MASK_DCRCFAILIE|SDIO_MASK_DTIMEOUTIE|\
+ SDIO_MASK_DATAENDIE|SDIO_MASK_RXOVERRIE|\
+ SDIO_MASK_RXFIFOHFIE|SDIO_MASK_STBITERRIE)
+#define SDIO_SEND_MASK (SDIO_MASK_DCRCFAILIE|SDIO_MASK_DTIMEOUTIE|\
+ SDIO_MASK_DATAENDIE|SDIO_MASK_TXUNDERRIE|\
+ SDIO_MASK_TXFIFOHEIE|SDIO_MASK_STBITERRIE)
+#define SDIO_DMARECV_MASK (SDIO_MASK_DCRCFAILIE|SDIO_MASK_DTIMEOUTIE|\
+ SDIO_MASK_DATAENDIE|SDIO_MASK_RXOVERRIE|\
+ SDIO_MASK_STBITERRIE)
+#define SDIO_DMASEND_MASK (SDIO_MASK_DCRCFAILIE|SDIO_MASK_DTIMEOUTIE|\
+ SDIO_MASK_DATAENDIE|SDIO_MASK_TXUNDERRIE|\
+ SDIO_MASK_STBITERRIE)
+
+/* Event waiting interrupt mask bits */
+
+#define SDIO_CMDDONE_STA (SDIO_STA_CMDSENT)
+#define SDIO_RESPDONE_STA (SDIO_STA_CTIMEOUT|SDIO_STA_CCRCFAIL|\
+ SDIO_STA_CMDREND)
+#define SDIO_XFRDONE_STA (0)
+
+#define SDIO_CMDDONE_MASK (SDIO_MASK_CMDSENTIE)
+#define SDIO_RESPDONE_MASK (SDIO_MASK_CCRCFAILIE|SDIO_MASK_CTIMEOUTIE|\
+ SDIO_MASK_CMDRENDIE)
+#define SDIO_XFRDONE_MASK (0)
+
+#define SDIO_CMDDONE_ICR (SDIO_ICR_CMDSENTC)
+#define SDIO_RESPDONE_ICR (SDIO_ICR_CTIMEOUTC|SDIO_ICR_CCRCFAILC|\
+ SDIO_ICR_CMDRENDC)
+#define SDIO_XFRDONE_ICR (SDIO_ICR_DATAENDC|SDIO_ICR_DCRCFAILC|\
+ SDIO_ICR_DTIMEOUTC|SDIO_ICR_RXOVERRC|\
+ SDIO_ICR_TXUNDERRC|SDIO_ICR_STBITERRC)
+
+#define SDIO_WAITALL_ICR (SDIO_CMDDONE_ICR|SDIO_RESPDONE_ICR|\
+ SDIO_XFRDONE_ICR)
+
+/* Let's wait until we have both SDIO transfer complete and DMA complete. */
+
+#define SDIO_XFRDONE_FLAG (1)
+#define SDIO_DMADONE_FLAG (2)
+#define SDIO_ALLDONE (3)
+
+/* Register logging support */
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+# ifdef CONFIG_SDIO_DMA
+# define SAMPLENDX_BEFORE_SETUP 0
+# define SAMPLENDX_BEFORE_ENABLE 1
+# define SAMPLENDX_AFTER_SETUP 2
+# define SAMPLENDX_END_TRANSFER 3
+# define SAMPLENDX_DMA_CALLBACK 4
+# define DEBUG_NSAMPLES 5
+# else
+# define SAMPLENDX_BEFORE_SETUP 0
+# define SAMPLENDX_AFTER_SETUP 1
+# define SAMPLENDX_END_TRANSFER 2
+# define DEBUG_NSAMPLES 3
+# endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure defines the state of the STM32 SDIO interface */
+
+struct stm32_dev_s
+{
+ struct sdio_dev_s dev; /* Standard, base SDIO interface */
+
+ /* STM32-specific extensions */
+ /* Event support */
+
+ sem_t waitsem; /* Implements event waiting */
+ sdio_eventset_t waitevents; /* Set of events to be waited for */
+ uint32_t waitmask; /* Interrupt enables for event waiting */
+ volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */
+ WDOG_ID waitwdog; /* Watchdog that handles event timeouts */
+
+ /* Callback support */
+
+ uint8_t cdstatus; /* Card status */
+ sdio_eventset_t cbevents; /* Set of events to be cause callbacks */
+ worker_t callback; /* Registered callback function */
+ void *cbarg; /* Registered callback argument */
+ struct work_s cbwork; /* Callback work queue structure */
+
+ /* Interrupt mode data transfer support */
+
+ uint32_t *buffer; /* Address of current R/W buffer */
+ size_t remaining; /* Number of bytes remaining in the transfer */
+ uint32_t xfrmask; /* Interrupt enables for data transfer */
+
+ /* DMA data transfer support */
+
+ bool widebus; /* Required for DMA support */
+#ifdef CONFIG_SDIO_DMA
+ volatile uint8_t xfrflags; /* Used to synchronize SDIO and DMA completion events */
+ bool dmamode; /* true: DMA mode transfer */
+ DMA_HANDLE dma; /* Handle for DMA channel */
+#endif
+};
+
+/* Register logging support */
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+struct stm32_sdioregs_s
+{
+ uint8_t power;
+ uint16_t clkcr;
+ uint16_t dctrl;
+ uint32_t dtimer;
+ uint32_t dlen;
+ uint32_t dcount;
+ uint32_t sta;
+ uint32_t mask;
+ uint32_t fifocnt;
+};
+
+struct stm32_sampleregs_s
+{
+ struct stm32_sdioregs_s sdio;
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ struct stm32_dmaregs_s dma;
+#endif
+};
+#endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Low-level helpers ********************************************************/
+
+static void stm32_takesem(struct stm32_dev_s *priv);
+#define stm32_givesem(priv) (sem_post(&priv->waitsem))
+static inline void stm32_setclkcr(uint32_t clkcr);
+static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask,
+ sdio_eventset_t waitevents, sdio_eventset_t wkupevents);
+static void stm32_configxfrints(struct stm32_dev_s *priv, uint32_t xfrmask);
+static void stm32_setpwrctrl(uint32_t pwrctrl);
+static inline uint32_t stm32_getpwrctrl(void);
+
+/* DMA Helpers **************************************************************/
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+static void stm32_sampleinit(void);
+static void stm32_sdiosample(struct stm32_sdioregs_s *regs);
+static void stm32_sample(struct stm32_dev_s *priv, int index);
+static void stm32_sdiodump(struct stm32_sdioregs_s *regs, const char *msg);
+static void stm32_dumpsample(struct stm32_dev_s *priv,
+ struct stm32_sampleregs_s *regs, const char *msg);
+static void stm32_dumpsamples(struct stm32_dev_s *priv);
+#else
+# define stm32_sampleinit()
+# define stm32_sample(priv,index)
+# define stm32_dumpsamples(priv)
+#endif
+
+#ifdef CONFIG_SDIO_DMA
+static void stm32_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg);
+#endif
+
+/* Data Transfer Helpers ****************************************************/
+
+static uint8_t stm32_log2(uint16_t value);
+static void stm32_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl);
+static void stm32_datadisable(void);
+static void stm32_sendfifo(struct stm32_dev_s *priv);
+static void stm32_recvfifo(struct stm32_dev_s *priv);
+static void stm32_eventtimeout(int argc, uint32_t arg);
+static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent);
+static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupevent);
+
+/* Interrupt Handling *******************************************************/
+
+static int stm32_interrupt(int irq, void *context);
+
+/* SDIO interface methods ***************************************************/
+
+/* Mutual exclusion */
+
+#ifdef CONFIG_SDIO_MUXBUS
+static int stm32_lock(FAR struct sdio_dev_s *dev, bool lock);
+#endif
+
+/* Initialization/setup */
+
+static void stm32_reset(FAR struct sdio_dev_s *dev);
+static uint8_t stm32_status(FAR struct sdio_dev_s *dev);
+static void stm32_widebus(FAR struct sdio_dev_s *dev, bool enable);
+static void stm32_clock(FAR struct sdio_dev_s *dev,
+ enum sdio_clock_e rate);
+static int stm32_attach(FAR struct sdio_dev_s *dev);
+
+/* Command/Status/Data Transfer */
+
+static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t arg);
+static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
+ size_t nbytes);
+static int stm32_sendsetup(FAR struct sdio_dev_s *dev,
+ FAR const uint8_t *buffer, uint32_t nbytes);
+static int stm32_cancel(FAR struct sdio_dev_s *dev);
+
+static int stm32_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd);
+static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t *rshort);
+static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t rlong[4]);
+static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t *rshort);
+static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t *rnotimpl);
+
+/* EVENT handler */
+
+static void stm32_waitenable(FAR struct sdio_dev_s *dev,
+ sdio_eventset_t eventset);
+static sdio_eventset_t
+ stm32_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
+static void stm32_callbackenable(FAR struct sdio_dev_s *dev,
+ sdio_eventset_t eventset);
+static int stm32_registercallback(FAR struct sdio_dev_s *dev,
+ worker_t callback, void *arg);
+
+/* DMA */
+
+#ifdef CONFIG_SDIO_DMA
+static bool stm32_dmasupported(FAR struct sdio_dev_s *dev);
+static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev,
+ FAR uint8_t *buffer, size_t buflen);
+static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
+ FAR const uint8_t *buffer, size_t buflen);
+#endif
+
+/* Initialization/uninitialization/reset ************************************/
+
+static void stm32_callback(void *arg);
+static void stm32_default(void);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct stm32_dev_s g_sdiodev =
+{
+ .dev =
+ {
+#ifdef CONFIG_SDIO_MUXBUS
+ .lock = stm32_lock,
+#endif
+ .reset = stm32_reset,
+ .status = stm32_status,
+ .widebus = stm32_widebus,
+ .clock = stm32_clock,
+ .attach = stm32_attach,
+ .sendcmd = stm32_sendcmd,
+ .recvsetup = stm32_recvsetup,
+ .sendsetup = stm32_sendsetup,
+ .cancel = stm32_cancel,
+ .waitresponse = stm32_waitresponse,
+ .recvR1 = stm32_recvshortcrc,
+ .recvR2 = stm32_recvlong,
+ .recvR3 = stm32_recvshort,
+ .recvR4 = stm32_recvnotimpl,
+ .recvR5 = stm32_recvnotimpl,
+ .recvR6 = stm32_recvshortcrc,
+ .recvR7 = stm32_recvshort,
+ .waitenable = stm32_waitenable,
+ .eventwait = stm32_eventwait,
+ .callbackenable = stm32_callbackenable,
+ .registercallback = stm32_registercallback,
+#ifdef CONFIG_SDIO_DMA
+ .dmasupported = stm32_dmasupported,
+ .dmarecvsetup = stm32_dmarecvsetup,
+ .dmasendsetup = stm32_dmasendsetup,
+#endif
+ },
+};
+
+/* Register logging support */
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+static struct stm32_sampleregs_s g_sampleregs[DEBUG_NSAMPLES];
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Low-level Helpers
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_takesem
+ *
+ * Description:
+ * Take the wait semaphore (handling false alarm wakeups due to the receipt
+ * of signals).
+ *
+ * Input Parameters:
+ * dev - Instance of the SDIO device driver state structure.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_takesem(struct stm32_dev_s *priv)
+{
+ /* Take the semaphore (perhaps waiting) */
+
+ while (sem_wait(&priv->waitsem) != 0)
+ {
+ /* The only case that an error should occr here is if the wait was
+ * awakened by a signal.
+ */
+
+ ASSERT(errno == EINTR);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_setclkcr
+ *
+ * Description:
+ * Modify oft-changed bits in the CLKCR register. Only the following bit-
+ * fields are changed:
+ *
+ * CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, and HWFC_EN
+ *
+ * Input Parameters:
+ * clkcr - A new CLKCR setting for the above mentions bits (other bits
+ * are ignored.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static inline void stm32_setclkcr(uint32_t clkcr)
+{
+ uint32_t regval = getreg32(STM32_SDIO_CLKCR);
+
+ /* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */
+
+ regval &= ~(SDIO_CLKCR_CLKDIV_MASK|SDIO_CLKCR_PWRSAV|SDIO_CLKCR_BYPASS|
+ SDIO_CLKCR_WIDBUS_MASK|SDIO_CLKCR_NEGEDGE|SDIO_CLKCR_HWFC_EN|
+ SDIO_CLKCR_CLKEN);
+
+ /* Replace with user provided settings */
+
+ clkcr &= (SDIO_CLKCR_CLKDIV_MASK|SDIO_CLKCR_PWRSAV|SDIO_CLKCR_BYPASS|
+ SDIO_CLKCR_WIDBUS_MASK|SDIO_CLKCR_NEGEDGE|SDIO_CLKCR_HWFC_EN|
+ SDIO_CLKCR_CLKEN);
+
+ regval |= clkcr;
+ putreg32(regval, STM32_SDIO_CLKCR);
+
+ fvdbg("CLKCR: %08x PWR: %08x\n",
+ getreg32(STM32_SDIO_CLKCR), getreg32(STM32_SDIO_POWER));
+}
+
+/****************************************************************************
+ * Name: stm32_configwaitints
+ *
+ * Description:
+ * Enable/disable SDIO interrupts needed to suport the wait function
+ *
+ * Input Parameters:
+ * priv - A reference to the SDIO device state structure
+ * waitmask - The set of bits in the SDIO MASK register to set
+ * waitevents - Waited for events
+ * wkupevent - Wake-up events
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask,
+ sdio_eventset_t waitevents,
+ sdio_eventset_t wkupevent)
+{
+ irqstate_t flags;
+
+ /* Save all of the data and set the new interrupt mask in one, atomic
+ * operation.
+ */
+
+ flags = irqsave();
+ priv->waitevents = waitevents;
+ priv->wkupevent = wkupevent;
+ priv->waitmask = waitmask;
+#ifdef CONFIG_SDIO_DMA
+ priv->xfrflags = 0;
+#endif
+ putreg32(priv->xfrmask | priv->waitmask, STM32_SDIO_MASK);
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: stm32_configxfrints
+ *
+ * Description:
+ * Enable SDIO interrupts needed to support the data transfer event
+ *
+ * Input Parameters:
+ * priv - A reference to the SDIO device state structure
+ * xfrmask - The set of bits in the SDIO MASK register to set
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_configxfrints(struct stm32_dev_s *priv, uint32_t xfrmask)
+{
+ irqstate_t flags;
+ flags = irqsave();
+ priv->xfrmask = xfrmask;
+ putreg32(priv->xfrmask | priv->waitmask, STM32_SDIO_MASK);
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: stm32_setpwrctrl
+ *
+ * Description:
+ * Change the PWRCTRL field of the SDIO POWER register to turn the SDIO
+ * ON or OFF
+ *
+ * Input Parameters:
+ * clkcr - A new PWRCTRL setting
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_setpwrctrl(uint32_t pwrctrl)
+{
+ uint32_t regval;
+
+ regval = getreg32(STM32_SDIO_POWER);
+ regval &= ~SDIO_POWER_PWRCTRL_MASK;
+ regval |= pwrctrl;
+ putreg32(regval, STM32_SDIO_POWER);
+}
+
+/****************************************************************************
+ * Name: stm32_getpwrctrl
+ *
+ * Description:
+ * Return the current value of the the PWRCTRL field of the SDIO POWER
+ * register. This function can be used to see the the SDIO is power ON
+ * or OFF
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * The current value of the the PWRCTRL field of the SDIO POWER register.
+ *
+ ****************************************************************************/
+
+static inline uint32_t stm32_getpwrctrl(void)
+{
+ return getreg32(STM32_SDIO_POWER) & SDIO_POWER_PWRCTRL_MASK;
+}
+
+/****************************************************************************
+ * DMA Helpers
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_sampleinit
+ *
+ * Description:
+ * Setup prior to collecting DMA samples
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+static void stm32_sampleinit(void)
+{
+ memset(g_sampleregs, 0xff, DEBUG_NSAMPLES * sizeof(struct stm32_sampleregs_s));
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_sdiosample
+ *
+ * Description:
+ * Sample SDIO registers
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+static void stm32_sdiosample(struct stm32_sdioregs_s *regs)
+{
+ regs->power = (uint8_t)getreg32(STM32_SDIO_POWER);
+ regs->clkcr = (uint16_t)getreg32(STM32_SDIO_CLKCR);
+ regs->dctrl = (uint16_t)getreg32(STM32_SDIO_DCTRL);
+ regs->dtimer = getreg32(STM32_SDIO_DTIMER);
+ regs->dlen = getreg32(STM32_SDIO_DLEN);
+ regs->dcount = getreg32(STM32_SDIO_DCOUNT);
+ regs->sta = getreg32(STM32_SDIO_STA);
+ regs->mask = getreg32(STM32_SDIO_MASK);
+ regs->fifocnt = getreg32(STM32_SDIO_FIFOCNT);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_sample
+ *
+ * Description:
+ * Sample SDIO/DMA registers
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+static void stm32_sample(struct stm32_dev_s *priv, int index)
+{
+ struct stm32_sampleregs_s *regs = &g_sampleregs[index];
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ if (priv->dmamode)
+ {
+ stm32_dmasample(priv->dma, &regs->dma);
+ }
+#endif
+ stm32_sdiosample(&regs->sdio);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_sdiodump
+ *
+ * Description:
+ * Dump one register sample
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+static void stm32_sdiodump(struct stm32_sdioregs_s *regs, const char *msg)
+{
+ fdbg("SDIO Registers: %s\n", msg);
+ fdbg(" POWER[%08x]: %08x\n", STM32_SDIO_POWER, regs->power);
+ fdbg(" CLKCR[%08x]: %08x\n", STM32_SDIO_CLKCR, regs->clkcr);
+ fdbg(" DCTRL[%08x]: %08x\n", STM32_SDIO_DCTRL, regs->dctrl);
+ fdbg(" DTIMER[%08x]: %08x\n", STM32_SDIO_DTIMER, regs->dtimer);
+ fdbg(" DLEN[%08x]: %08x\n", STM32_SDIO_DLEN, regs->dlen);
+ fdbg(" DCOUNT[%08x]: %08x\n", STM32_SDIO_DCOUNT, regs->dcount);
+ fdbg(" STA[%08x]: %08x\n", STM32_SDIO_STA, regs->sta);
+ fdbg(" MASK[%08x]: %08x\n", STM32_SDIO_MASK, regs->mask);
+ fdbg("FIFOCNT[%08x]: %08x\n", STM32_SDIO_FIFOCNT, regs->fifocnt);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_dumpsample
+ *
+ * Description:
+ * Dump one register sample
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+static void stm32_dumpsample(struct stm32_dev_s *priv,
+ struct stm32_sampleregs_s *regs, const char *msg)
+{
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ if (priv->dmamode)
+ {
+ stm32_dmadump(priv->dma, &regs->dma, msg);
+ }
+#endif
+ stm32_sdiodump(&regs->sdio, msg);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_dumpsamples
+ *
+ * Description:
+ * Dump all sampled register data
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_XFRDEBUG
+static void stm32_dumpsamples(struct stm32_dev_s *priv)
+{
+ stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP], "Before setup");
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ if (priv->dmamode)
+ {
+ stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_ENABLE], "Before DMA enable");
+ }
+#endif
+ stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP], "After setup");
+ stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER], "End of transfer");
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ if (priv->dmamode)
+ {
+ stm32_dumpsample(priv, &g_sampleregs[SAMPLENDX_DMA_CALLBACK], "DMA Callback");
+ }
+#endif
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_dmacallback
+ *
+ * Description:
+ * Called when SDIO DMA completes
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static void stm32_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)arg;
+ DEBUGASSERT(priv->dmamode);
+ sdio_eventset_t result;
+
+ /* In the normal case, SDIO appears to handle the End-Of-Transfer interrupt
+ * first with the End-Of-DMA event occurring significantly later. On
+ * transfer errors, however, the DMA error will occur before the End-of-
+ * Transfer.
+ */
+
+ stm32_sample((struct stm32_dev_s*)arg, SAMPLENDX_DMA_CALLBACK);
+
+ /* Get the result of the DMA transfer */
+
+ if ((status & DMA_STATUS_ERROR) != 0)
+ {
+ flldbg("DMA error %02x, remaining: %d\n", status, priv->remaining);
+ result = SDIOWAIT_ERROR;
+ }
+ else
+ {
+ result = SDIOWAIT_TRANSFERDONE;
+ }
+
+ /* Then terminate the transfer if this completes all of the steps in the
+ * transfer OR if a DMA error occurred. In the non-error case, we should
+ * already have the SDIO transfer done interrupt. If not, the transfer
+ * will appropriately time out.
+ */
+
+ priv->xfrflags |= SDIO_DMADONE_FLAG;
+ if (priv->xfrflags == SDIO_ALLDONE || result == SDIOWAIT_ERROR)
+ {
+ stm32_endtransfer(priv, result);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Data Transfer Helpers
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_log2
+ *
+ * Description:
+ * Take (approximate) log base 2 of the provided number (Only works if the
+ * provided number is a power of 2).
+ *
+ ****************************************************************************/
+
+static uint8_t stm32_log2(uint16_t value)
+{
+ uint8_t log2 = 0;
+
+ /* 0000 0000 0000 0001 -> return 0,
+ * 0000 0000 0000 001x -> return 1,
+ * 0000 0000 0000 01xx -> return 2,
+ * 0000 0000 0000 1xxx -> return 3,
+ * ...
+ * 1xxx xxxx xxxx xxxx -> return 15,
+ */
+
+ DEBUGASSERT(value > 0);
+ while (value != 1)
+ {
+ value >>= 1;
+ log2++;
+ }
+ return log2;
+}
+
+/****************************************************************************
+ * Name: stm32_dataconfig
+ *
+ * Description:
+ * Configure the SDIO data path for the next data transfer
+ *
+ ****************************************************************************/
+
+static void stm32_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl)
+{
+ uint32_t regval = 0;
+
+ /* Enable data path */
+
+ putreg32(timeout, STM32_SDIO_DTIMER); /* Set DTIMER */
+ putreg32(dlen, STM32_SDIO_DLEN); /* Set DLEN */
+
+ /* Configure DCTRL DTDIR, DTMODE, and DBLOCKSIZE fields and set the DTEN
+ * field
+ */
+
+ regval = getreg32(STM32_SDIO_DCTRL);
+ regval &= ~(SDIO_DCTRL_DTDIR|SDIO_DCTRL_DTMODE|SDIO_DCTRL_DBLOCKSIZE_MASK);
+ dctrl &= (SDIO_DCTRL_DTDIR|SDIO_DCTRL_DTMODE|SDIO_DCTRL_DBLOCKSIZE_MASK);
+ regval |= (dctrl|SDIO_DCTRL_DTEN);
+ putreg32(regval, STM32_SDIO_DCTRL);
+}
+
+/****************************************************************************
+ * Name: stm32_datadisable
+ *
+ * Description:
+ * Disable the the SDIO data path setup by stm32_dataconfig() and
+ * disable DMA.
+ *
+ ****************************************************************************/
+
+static void stm32_datadisable(void)
+{
+ uint32_t regval;
+
+ /* Disable the data path */
+
+ putreg32(SDIO_DTIMER_DATATIMEOUT, STM32_SDIO_DTIMER); /* Reset DTIMER */
+ putreg32(0, STM32_SDIO_DLEN); /* Reset DLEN */
+
+ /* Reset DCTRL DTEN, DTDIR, DTMODE, DMAEN, and DBLOCKSIZE fields */
+
+ regval = getreg32(STM32_SDIO_DCTRL);
+ regval &= ~(SDIO_DCTRL_DTEN|SDIO_DCTRL_DTDIR|SDIO_DCTRL_DTMODE|
+ SDIO_DCTRL_DMAEN|SDIO_DCTRL_DBLOCKSIZE_MASK);
+ putreg32(regval, STM32_SDIO_DCTRL);
+}
+
+/****************************************************************************
+ * Name: stm32_sendfifo
+ *
+ * Description:
+ * Send SDIO data in interrupt mode
+ *
+ * Input Parameters:
+ * priv - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_sendfifo(struct stm32_dev_s *priv)
+{
+ union
+ {
+ uint32_t w;
+ uint8_t b[4];
+ } data;
+
+ /* Loop while there is more data to be sent and the RX FIFO is not full */
+
+ while (priv->remaining > 0 &&
+ (getreg32(STM32_SDIO_STA) & SDIO_STA_TXFIFOF) == 0)
+ {
+ /* Is there a full word remaining in the user buffer? */
+
+ if (priv->remaining >= sizeof(uint32_t))
+ {
+ /* Yes, transfer the word to the TX FIFO */
+
+ data.w = *priv->buffer++;
+ priv->remaining -= sizeof(uint32_t);
+ }
+ else
+ {
+ /* No.. transfer just the bytes remaining in the user buffer,
+ * padding with zero as necessary to extend to a full word.
+ */
+
+ uint8_t *ptr = (uint8_t *)priv->remaining;
+ int i;
+
+ data.w = 0;
+ for (i = 0; i < priv->remaining; i++)
+ {
+ data.b[i] = *ptr++;
+ }
+
+ /* Now the transfer is finished */
+
+ priv->remaining = 0;
+ }
+
+ /* Put the word in the FIFO */
+
+ putreg32(data.w, STM32_SDIO_FIFO);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_recvfifo
+ *
+ * Description:
+ * Receive SDIO data in interrupt mode
+ *
+ * Input Parameters:
+ * priv - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_recvfifo(struct stm32_dev_s *priv)
+{
+ union
+ {
+ uint32_t w;
+ uint8_t b[4];
+ } data;
+
+ /* Loop while there is space to store the data and there is more
+ * data available in the RX FIFO.
+ */
+
+ while (priv->remaining > 0 &&
+ (getreg32(STM32_SDIO_STA) & SDIO_STA_RXDAVL) != 0)
+ {
+ /* Read the next word from the RX FIFO */
+
+ data.w = getreg32(STM32_SDIO_FIFO);
+ if (priv->remaining >= sizeof(uint32_t))
+ {
+ /* Transfer the whole word to the user buffer */
+
+ *priv->buffer++ = data.w;
+ priv->remaining -= sizeof(uint32_t);
+ }
+ else
+ {
+ /* Transfer any trailing fractional word */
+
+ uint8_t *ptr = (uint8_t*)priv->buffer;
+ int i;
+
+ for (i = 0; i < priv->remaining; i++)
+ {
+ *ptr++ = data.b[i];
+ }
+
+ /* Now the transfer is finished */
+
+ priv->remaining = 0;
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_eventtimeout
+ *
+ * Description:
+ * The watchdog timeout setup when the event wait start has expired without
+ * any other waited-for event occurring.
+ *
+ * Input Parameters:
+ * argc - The number of arguments (should be 1)
+ * arg - The argument (state structure reference cast to uint32_t)
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Always called from the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static void stm32_eventtimeout(int argc, uint32_t arg)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)arg;
+
+ /* There is always race conditions with timer expirations. */
+
+ DEBUGASSERT((priv->waitevents & SDIOWAIT_TIMEOUT) != 0 || priv->wkupevent != 0);
+
+ /* Is a data transfer complete event expected? */
+
+ if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
+ {
+ /* Yes.. wake up any waiting threads */
+
+ stm32_endwait(priv, SDIOWAIT_TIMEOUT);
+ flldbg("Timeout: remaining: %d\n", priv->remaining);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_endwait
+ *
+ * Description:
+ * Wake up a waiting thread if the waited-for event has occurred.
+ *
+ * Input Parameters:
+ * priv - An instance of the SDIO device interface
+ * wkupevent - The event that caused the wait to end
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Always called from the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent)
+{
+ /* Cancel the watchdog timeout */
+
+ (void)wd_cancel(priv->waitwdog);
+
+ /* Disable event-related interrupts */
+
+ stm32_configwaitints(priv, 0, 0, wkupevent);
+
+ /* Wake up the waiting thread */
+
+ stm32_givesem(priv);
+}
+
+/****************************************************************************
+ * Name: stm32_endtransfer
+ *
+ * Description:
+ * Terminate a transfer with the provided status. This function is called
+ * only from the SDIO interrupt handler when end-of-transfer conditions
+ * are detected.
+ *
+ * Input Parameters:
+ * priv - An instance of the SDIO device interface
+ * wkupevent - The event that caused the transfer to end
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Always called from the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupevent)
+{
+ /* Disable all transfer related interrupts */
+
+ stm32_configxfrints(priv, 0);
+
+ /* Clearing pending interrupt status on all transfer related interrupts */
+
+ putreg32(SDIO_XFRDONE_ICR, STM32_SDIO_ICR);
+
+ /* If this was a DMA transfer, make sure that DMA is stopped */
+
+#ifdef CONFIG_SDIO_DMA
+ if (priv->dmamode)
+ {
+ /* DMA debug instrumentation */
+
+ stm32_sample(priv, SAMPLENDX_END_TRANSFER);
+
+ /* Make sure that the DMA is stopped (it will be stopped automatically
+ * on normal transfers, but not necessarily when the transfer terminates
+ * on an error condition).
+ */
+
+ stm32_dmastop(priv->dma);
+ }
+#endif
+
+ /* Mark the transfer finished */
+
+ priv->remaining = 0;
+
+ /* Is a thread wait for these data transfer complete events? */
+
+ if ((priv->waitevents & wkupevent) != 0)
+ {
+ /* Yes.. wake up any waiting threads */
+
+ stm32_endwait(priv, wkupevent);
+ }
+}
+
+/****************************************************************************
+ * Interrrupt Handling
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_interrupt
+ *
+ * Description:
+ * SDIO interrupt handler
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static int stm32_interrupt(int irq, void *context)
+{
+ struct stm32_dev_s *priv = &g_sdiodev;
+ uint32_t enabled;
+ uint32_t pending;
+
+ /* Loop while there are pending interrupts. Check the SDIO status
+ * register. Mask out all bits that don't correspond to enabled
+ * interrupts. (This depends on the fact that bits are ordered
+ * the same in both the STA and MASK register). If there are non-zero
+ * bits remaining, then we have work to do here.
+ */
+
+ while ((enabled = getreg32(STM32_SDIO_STA) & getreg32(STM32_SDIO_MASK)) != 0)
+ {
+ /* Handle in progress, interrupt driven data transfers ****************/
+
+ pending = enabled & priv->xfrmask;
+ if (pending != 0)
+ {
+#ifdef CONFIG_SDIO_DMA
+ if (!priv->dmamode)
+#endif
+ {
+ /* Is the RX FIFO half full or more? Is so then we must be
+ * processing a receive transaction.
+ */
+
+ if ((pending & SDIO_STA_RXFIFOHF) != 0)
+ {
+ /* Receive data from the RX FIFO */
+
+ stm32_recvfifo(priv);
+ }
+
+ /* Otherwise, Is the transmit FIFO half empty or less? If so we must
+ * be processing a send transaction. NOTE: We can't be processing
+ * both!
+ */
+
+ else if ((pending & SDIO_STA_TXFIFOHE) != 0)
+ {
+ /* Send data via the TX FIFO */
+
+ stm32_sendfifo(priv);
+ }
+ }
+
+ /* Handle data end events */
+
+ if ((pending & SDIO_STA_DATAEND) != 0)
+ {
+ /* Handle any data remaining the RX FIFO. If the RX FIFO is
+ * less than half full at the end of the transfer, then no
+ * half-full interrupt will be received.
+ */
+
+ /* Was this transfer performed in DMA mode? */
+
+#ifdef CONFIG_SDIO_DMA
+ if (priv->dmamode)
+ {
+ /* Yes.. Terminate the transfers only if the DMA has also
+ * finished.
+ */
+
+ priv->xfrflags |= SDIO_XFRDONE_FLAG;
+ if (priv->xfrflags == SDIO_ALLDONE)
+ {
+ stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
+ }
+
+ /* Otherwise, just disable futher transfer interrupts and
+ * wait for the DMA complete event.
+ */
+
+ else
+ {
+ stm32_configxfrints(priv, 0);
+ }
+ }
+ else
+#endif
+ {
+ /* Receive data from the RX FIFO */
+
+ stm32_recvfifo(priv);
+
+ /* Then terminate the transfer */
+
+ stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
+ }
+ }
+
+ /* Handle data block send/receive CRC failure */
+
+ else if ((pending & SDIO_STA_DCRCFAIL) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: Data block CRC failure, remaining: %d\n", priv->remaining);
+ stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
+ }
+
+ /* Handle data timeout error */
+
+ else if ((pending & SDIO_STA_DTIMEOUT) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: Data timeout, remaining: %d\n", priv->remaining);
+ stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT);
+ }
+
+ /* Handle RX FIFO overrun error */
+
+ else if ((pending & SDIO_STA_RXOVERR) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: RX FIFO overrun, remaining: %d\n", priv->remaining);
+ stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
+ }
+
+ /* Handle TX FIFO underrun error */
+
+ else if ((pending & SDIO_STA_TXUNDERR) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: TX FIFO underrun, remaining: %d\n", priv->remaining);
+ stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
+ }
+
+ /* Handle start bit error */
+
+ else if ((pending & SDIO_STA_STBITERR) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: Start bit, remaining: %d\n", priv->remaining);
+ stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
+ }
+ }
+
+ /* Handle wait events *************************************************/
+
+ pending = enabled & priv->waitmask;
+ if (pending != 0)
+ {
+ /* Is this a response completion event? */
+
+ if ((pending & SDIO_RESPDONE_STA) != 0)
+ {
+ /* Yes.. Is their a thread waiting for response done? */
+
+ if ((priv->waitevents & SDIOWAIT_RESPONSEDONE) != 0)
+ {
+ /* Yes.. wake the thread up */
+
+ putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
+ stm32_endwait(priv, SDIOWAIT_RESPONSEDONE);
+ }
+ }
+
+ /* Is this a command completion event? */
+
+ if ((pending & SDIO_CMDDONE_STA) != 0)
+ {
+ /* Yes.. Is their a thread waiting for command done? */
+
+ if ((priv->waitevents & SDIOWAIT_RESPONSEDONE) != 0)
+ {
+ /* Yes.. wake the thread up */
+
+ putreg32(SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
+ stm32_endwait(priv, SDIOWAIT_CMDDONE);
+ }
+ }
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * SDIO Interface Methods
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_lock
+ *
+ * Description:
+ * Locks the bus. Function calls low-level multiplexed bus routines to
+ * resolve bus requests and acknowledgment issues.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * lock - TRUE to lock, FALSE to unlock.
+ *
+ * Returned Value:
+ * OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_MUXBUS
+static int stm32_lock(FAR struct sdio_dev_s *dev, bool lock)
+{
+ /* Single SDIO instance so there is only one possibility. The multiplex
+ * bus is part of board support package.
+ */
+
+ stm32_muxbus_sdio_lock(lock);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_reset
+ *
+ * Description:
+ * Reset the SDIO controller. Undo all setup and initialization.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_reset(FAR struct sdio_dev_s *dev)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev;
+ irqstate_t flags;
+
+ /* Disable clocking */
+
+ flags = irqsave();
+ putreg32(0, SDIO_CLKCR_CLKEN_BB);
+ stm32_setpwrctrl(SDIO_POWER_PWRCTRL_OFF);
+
+ /* Put SDIO registers in their default, reset state */
+
+ stm32_default();
+
+ /* Reset data */
+
+ priv->waitevents = 0; /* Set of events to be waited for */
+ priv->waitmask = 0; /* Interrupt enables for event waiting */
+ priv->wkupevent = 0; /* The event that caused the wakeup */
+#ifdef CONFIG_SDIO_DMA
+ priv->xfrflags = 0; /* Used to synchronize SDIO and DMA completion events */
+#endif
+
+ wd_cancel(priv->waitwdog); /* Cancel any timeouts */
+
+ /* Interrupt mode data transfer support */
+
+ priv->buffer = 0; /* Address of current R/W buffer */
+ priv->remaining = 0; /* Number of bytes remaining in the transfer */
+ priv->xfrmask = 0; /* Interrupt enables for data transfer */
+
+ /* DMA data transfer support */
+
+ priv->widebus = false; /* Required for DMA support */
+#ifdef CONFIG_SDIO_DMA
+ priv->dmamode = false; /* true: DMA mode transfer */
+#endif
+
+ /* Configure the SDIO peripheral */
+
+ stm32_setclkcr(STM32_CLCKCR_INIT | SDIO_CLKCR_CLKEN);
+ stm32_setpwrctrl(SDIO_POWER_PWRCTRL_ON);
+ irqrestore(flags);
+
+ fvdbg("CLCKR: %08x POWER: %08x\n",
+ getreg32(STM32_SDIO_CLKCR), getreg32(STM32_SDIO_POWER));
+}
+
+/****************************************************************************
+ * Name: stm32_status
+ *
+ * Description:
+ * Get SDIO status.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ *
+ * Returned Value:
+ * Returns a bitset of status values (see stm32_status_* defines)
+ *
+ ****************************************************************************/
+
+static uint8_t stm32_status(FAR struct sdio_dev_s *dev)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ return priv->cdstatus;
+}
+
+/****************************************************************************
+ * Name: stm32_widebus
+ *
+ * Description:
+ * Called after change in Bus width has been selected (via ACMD6). Most
+ * controllers will need to perform some special operations to work
+ * correctly in the new bus mode.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * wide - true: wide bus (4-bit) bus mode enabled
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_widebus(FAR struct sdio_dev_s *dev, bool wide)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ priv->widebus = wide;
+}
+
+/****************************************************************************
+ * Name: stm32_clock
+ *
+ * Description:
+ * Enable/disable SDIO clocking
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * rate - Specifies the clocking to use (see enum sdio_clock_e)
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
+{
+ uint32_t clckr;
+
+ switch (rate)
+ {
+ /* Disable clocking (with default ID mode divisor) */
+
+ default:
+ case CLOCK_SDIO_DISABLED:
+ clckr = STM32_CLCKCR_INIT;
+ return;
+
+ /* Enable in initial ID mode clocking (<400KHz) */
+
+ case CLOCK_IDMODE:
+ clckr = (STM32_CLCKCR_INIT | SDIO_CLKCR_CLKEN);
+ break;
+
+ /* Enable in MMC normal operation clocking */
+
+ case CLOCK_MMC_TRANSFER:
+ clckr = (SDIO_CLKCR_MMCXFR | SDIO_CLKCR_CLKEN);
+ break;
+
+ /* SD normal operation clocking (wide 4-bit mode) */
+
+ case CLOCK_SD_TRANSFER_4BIT:
+#ifndef CONFIG_SDIO_WIDTH_D1_ONLY
+ clckr = (SDIO_CLCKR_SDWIDEXFR | SDIO_CLKCR_CLKEN);
+ break;
+#endif
+
+ /* SD normal operation clocking (narrow 1-bit mode) */
+
+ case CLOCK_SD_TRANSFER_1BIT:
+ clckr = (SDIO_CLCKR_SDXFR | SDIO_CLKCR_CLKEN)
+ break;
+ }
+
+ /* Set the new clock frequency along with the clock enable/disable bit */
+
+ stm32_setclkcr(clckr);
+}
+
+/****************************************************************************
+ * Name: stm32_attach
+ *
+ * Description:
+ * Attach and prepare interrupts
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ * OK on success; A negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_attach(FAR struct sdio_dev_s *dev)
+{
+ int ret;
+
+ /* Attach the SDIO interrupt handler */
+
+ ret = irq_attach(STM32_IRQ_SDIO, stm32_interrupt);
+ if (ret == OK)
+ {
+
+ /* Disable all interrupts at the SDIO controller and clear static
+ * interrupt flags
+ */
+
+ putreg32(SDIO_MASK_RESET, STM32_SDIO_MASK);
+ putreg32(SDIO_ICR_STATICFLAGS, STM32_SDIO_ICR);
+
+ /* Enable SDIO interrupts at the NVIC. They can now be enabled at
+ * the SDIO controller as needed.
+ */
+
+ up_enable_irq(STM32_IRQ_SDIO);
+
+ /* Set the interrrupt priority */
+
+ up_prioritize_irq(STM32_IRQ_SDIO, CONFIG_SDIO_PRI);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: stm32_sendcmd
+ *
+ * Description:
+ * Send the SDIO command
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * cmd - The command to send (32-bits, encoded)
+ * arg - 32-bit argument required with some commands
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
+{
+ uint32_t regval;
+ uint32_t cmdidx;
+
+ /* Set the SDIO Argument value */
+
+ putreg32(arg, STM32_SDIO_ARG);
+
+ /* Clear CMDINDEX, WAITRESP, WAITINT, WAITPEND, and CPSMEN bits */
+
+ regval = getreg32(STM32_SDIO_CMD);
+ regval &= ~(SDIO_CMD_CMDINDEX_MASK|SDIO_CMD_WAITRESP_MASK|
+ SDIO_CMD_WAITINT|SDIO_CMD_WAITPEND|SDIO_CMD_CPSMEN);
+
+ /* Set WAITRESP bits */
+
+ switch (cmd & MMCSD_RESPONSE_MASK)
+ {
+ case MMCSD_NO_RESPONSE:
+ regval |= SDIO_CMD_NORESPONSE;
+ break;
+
+ case MMCSD_R1_RESPONSE:
+ case MMCSD_R1B_RESPONSE:
+ case MMCSD_R3_RESPONSE:
+ case MMCSD_R4_RESPONSE:
+ case MMCSD_R5_RESPONSE:
+ case MMCSD_R6_RESPONSE:
+ case MMCSD_R7_RESPONSE:
+ regval |= SDIO_CMD_SHORTRESPONSE;
+ break;
+
+ case MMCSD_R2_RESPONSE:
+ regval |= SDIO_CMD_LONGRESPONSE;
+ break;
+ }
+
+ /* Set CPSMEN and the command index */
+
+ cmdidx = (cmd & MMCSD_CMDIDX_MASK) >> MMCSD_CMDIDX_SHIFT;
+ regval |= cmdidx | SDIO_CMD_CPSMEN;
+
+ fvdbg("cmd: %08x arg: %08x regval: %08x\n", cmd, arg, regval);
+
+ /* Write the SDIO CMD */
+
+ putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
+ putreg32(regval, STM32_SDIO_CMD);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_recvsetup
+ *
+ * Description:
+ * Setup hardware in preparation for data transfer from the card in non-DMA
+ * (interrupt driven mode). This method will do whatever controller setup
+ * is necessary. This would be called for SD memory just BEFORE sending
+ * CMD13 (SEND_STATUS), CMD17 (READ_SINGLE_BLOCK), CMD18
+ * (READ_MULTIPLE_BLOCKS), ACMD51 (SEND_SCR), etc. Normally, SDIO_WAITEVENT
+ * will be called to receive the indication that the transfer is complete.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * buffer - Address of the buffer in which to receive the data
+ * nbytes - The number of bytes in the transfer
+ *
+ * Returned Value:
+ * Number of bytes sent on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
+ size_t nbytes)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ uint32_t dblocksize;
+
+ DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0);
+ DEBUGASSERT(((uint32_t)buffer & 3) == 0);
+
+ /* Reset the DPSM configuration */
+
+ stm32_datadisable();
+ stm32_sampleinit();
+ stm32_sample(priv, SAMPLENDX_BEFORE_SETUP);
+
+ /* Save the destination buffer information for use by the interrupt handler */
+
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = nbytes;
+#ifdef CONFIG_SDIO_DMA
+ priv->dmamode = false;
+#endif
+
+ /* Then set up the SDIO data path */
+
+ dblocksize = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
+ stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, nbytes, dblocksize|SDIO_DCTRL_DTDIR);
+
+ /* And enable interrupts */
+
+ stm32_configxfrints(priv, SDIO_RECV_MASK);
+ stm32_sample(priv, SAMPLENDX_AFTER_SETUP);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_sendsetup
+ *
+ * Description:
+ * Setup hardware in preparation for data transfer from the card. This method
+ * will do whatever controller setup is necessary. This would be called
+ * for SD memory just AFTER sending CMD24 (WRITE_BLOCK), CMD25
+ * (WRITE_MULTIPLE_BLOCK), ... and before SDIO_SENDDATA is called.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * buffer - Address of the buffer containing the data to send
+ * nbytes - The number of bytes in the transfer
+ *
+ * Returned Value:
+ * Number of bytes sent on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer,
+ size_t nbytes)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ uint32_t dblocksize;
+
+ DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0);
+ DEBUGASSERT(((uint32_t)buffer & 3) == 0);
+
+ /* Reset the DPSM configuration */
+
+ stm32_datadisable();
+ stm32_sampleinit();
+ stm32_sample(priv, SAMPLENDX_BEFORE_SETUP);
+
+ /* Save the source buffer information for use by the interrupt handler */
+
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = nbytes;
+#ifdef CONFIG_SDIO_DMA
+ priv->dmamode = false;
+#endif
+
+ /* Then set up the SDIO data path */
+
+ dblocksize = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
+ stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, nbytes, dblocksize);
+
+ /* Enable TX interrrupts */
+
+ stm32_configxfrints(priv, SDIO_SEND_MASK);
+ stm32_sample(priv, SAMPLENDX_AFTER_SETUP);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_cancel
+ *
+ * Description:
+ * Cancel the data transfer setup of SDIO_RECVSETUP, SDIO_SENDSETUP,
+ * SDIO_DMARECVSETUP or SDIO_DMASENDSETUP. This must be called to cancel
+ * the data transfer setup if, for some reason, you cannot perform the
+ * transfer.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ * OK is success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32_cancel(FAR struct sdio_dev_s *dev)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
+
+ /* Disable all transfer- and event- related interrupts */
+
+ stm32_configxfrints(priv, 0);
+ stm32_configwaitints(priv, 0, 0, 0);
+
+ /* Clearing pending interrupt status on all transfer- and event- related
+ * interrupts
+ */
+
+ putreg32(SDIO_WAITALL_ICR, STM32_SDIO_ICR);
+
+ /* Cancel any watchdog timeout */
+
+ (void)wd_cancel(priv->waitwdog);
+
+ /* If this was a DMA transfer, make sure that DMA is stopped */
+
+#ifdef CONFIG_SDIO_DMA
+ if (priv->dmamode)
+ {
+ /* Make sure that the DMA is stopped (it will be stopped automatically
+ * on normal transfers, but not necessarily when the transfer terminates
+ * on an error condition.
+ */
+
+ stm32_dmastop(priv->dma);
+ }
+#endif
+
+ /* Mark no transfer in progress */
+
+ priv->remaining = 0;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_waitresponse
+ *
+ * Description:
+ * Poll-wait for the response to the last command to be ready.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * cmd - The command that was sent. See 32-bit command definitions above.
+ *
+ * Returned Value:
+ * OK is success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
+{
+ int32_t timeout;
+ uint32_t events;
+
+ switch (cmd & MMCSD_RESPONSE_MASK)
+ {
+ case MMCSD_NO_RESPONSE:
+ events = SDIO_CMDDONE_STA;
+ timeout = SDIO_CMDTIMEOUT;
+ break;
+
+ case MMCSD_R1_RESPONSE:
+ case MMCSD_R1B_RESPONSE:
+ case MMCSD_R2_RESPONSE:
+ case MMCSD_R6_RESPONSE:
+ events = SDIO_RESPDONE_STA;
+ timeout = SDIO_LONGTIMEOUT;
+ break;
+
+ case MMCSD_R4_RESPONSE:
+ case MMCSD_R5_RESPONSE:
+ return -ENOSYS;
+
+ case MMCSD_R3_RESPONSE:
+ case MMCSD_R7_RESPONSE:
+ events = SDIO_RESPDONE_STA;
+ timeout = SDIO_CMDTIMEOUT;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Then wait for the response (or timeout) */
+
+ while ((getreg32(STM32_SDIO_STA) & events) == 0)
+ {
+ if (--timeout <= 0)
+ {
+ fdbg("ERROR: Timeout cmd: %08x events: %08x STA: %08x\n",
+ cmd, events, getreg32(STM32_SDIO_STA));
+
+ return -ETIMEDOUT;
+ }
+ }
+
+ putreg32(SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_recvRx
+ *
+ * Description:
+ * Receive response to SDIO command. Only the critical payload is
+ * returned -- that is 32 bits for 48 bit status and 128 bits for 136 bit
+ * status. The driver implementation should verify the correctness of
+ * the remaining, non-returned bits (CRCs, CMD index, etc.).
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * Rx - Buffer in which to receive the response
+ *
+ * Returned Value:
+ * Number of bytes sent on success; a negated errno on failure. Here a
+ * failure means only a faiure to obtain the requested reponse (due to
+ * transport problem -- timeout, CRC, etc.). The implementation only
+ * assures that the response is returned intacta and does not check errors
+ * within the response itself.
+ *
+ ****************************************************************************/
+
+static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort)
+{
+#ifdef CONFIG_DEBUG
+ uint32_t respcmd;
+#endif
+ uint32_t regval;
+ int ret = OK;
+
+ /* R1 Command response (48-bit)
+ * 47 0 Start bit
+ * 46 0 Transmission bit (0=from card)
+ * 45:40 bit5 - bit0 Command index (0-63)
+ * 39:8 bit31 - bit0 32-bit card status
+ * 7:1 bit6 - bit0 CRC7
+ * 0 1 End bit
+ *
+ * R1b Identical to R1 with the additional busy signaling via the data
+ * line.
+ *
+ * R6 Published RCA Response (48-bit, SD card only)
+ * 47 0 Start bit
+ * 46 0 Transmission bit (0=from card)
+ * 45:40 bit5 - bit0 Command index (0-63)
+ * 39:8 bit31 - bit0 32-bit Argument Field, consisting of:
+ * [31:16] New published RCA of card
+ * [15:0] Card status bits {23,22,19,12:0}
+ * 7:1 bit6 - bit0 CRC7
+ * 0 1 End bit
+ */
+
+
+#ifdef CONFIG_DEBUG
+ if (!rshort)
+ {
+ fdbg("ERROR: rshort=NULL\n");
+ ret = -EINVAL;
+ }
+
+ /* Check that this is the correct response to this command */
+
+ else if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1_RESPONSE &&
+ (cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1B_RESPONSE &&
+ (cmd & MMCSD_RESPONSE_MASK) != MMCSD_R6_RESPONSE)
+ {
+ fdbg("ERROR: Wrong response CMD=%08x\n", cmd);
+ ret = -EINVAL;
+ }
+ else
+#endif
+ {
+ /* Check if a timeout or CRC error occurred */
+
+ regval = getreg32(STM32_SDIO_STA);
+ if ((regval & SDIO_STA_CTIMEOUT) != 0)
+ {
+ fdbg("ERROR: Command timeout: %08x\n", regval);
+ ret = -ETIMEDOUT;
+ }
+ else if ((regval & SDIO_STA_CCRCFAIL) != 0)
+ {
+ fdbg("ERROR: CRC failure: %08x\n", regval);
+ ret = -EIO;
+ }
+#ifdef CONFIG_DEBUG
+ else
+ {
+ /* Check response received is of desired command */
+
+ respcmd = getreg32(STM32_SDIO_RESPCMD);
+ if ((uint8_t)(respcmd & SDIO_RESPCMD_MASK) != (cmd & MMCSD_CMDIDX_MASK))
+ {
+ fdbg("ERROR: RESCMD=%02x CMD=%08x\n", respcmd, cmd);
+ ret = -EINVAL;
+ }
+ }
+#endif
+ }
+
+ /* Clear all pending message completion events and return the R1/R6 response */
+
+ putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
+ *rshort = getreg32(STM32_SDIO_RESP1);
+ return ret;
+}
+
+static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t rlong[4])
+{
+ uint32_t regval;
+ int ret = OK;
+
+ /* R2 CID, CSD register (136-bit)
+ * 135 0 Start bit
+ * 134 0 Transmission bit (0=from card)
+ * 133:128 bit5 - bit0 Reserved
+ * 127:1 bit127 - bit1 127-bit CID or CSD register
+ * (including internal CRC)
+ * 0 1 End bit
+ */
+
+#ifdef CONFIG_DEBUG
+ /* Check that R1 is the correct response to this command */
+
+ if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R2_RESPONSE)
+ {
+ fdbg("ERROR: Wrong response CMD=%08x\n", cmd);
+ ret = -EINVAL;
+ }
+ else
+#endif
+ {
+ /* Check if a timeout or CRC error occurred */
+
+ regval = getreg32(STM32_SDIO_STA);
+ if (regval & SDIO_STA_CTIMEOUT)
+ {
+ fdbg("ERROR: Timeout STA: %08x\n", regval);
+ ret = -ETIMEDOUT;
+ }
+ else if (regval & SDIO_STA_CCRCFAIL)
+ {
+ fdbg("ERROR: CRC fail STA: %08x\n", regval);
+ ret = -EIO;
+ }
+ }
+
+ /* Return the long response */
+
+ putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
+ if (rlong)
+ {
+ rlong[0] = getreg32(STM32_SDIO_RESP1);
+ rlong[1] = getreg32(STM32_SDIO_RESP2);
+ rlong[2] = getreg32(STM32_SDIO_RESP3);
+ rlong[3] = getreg32(STM32_SDIO_RESP4);
+ }
+ return ret;
+}
+
+static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort)
+{
+ uint32_t regval;
+ int ret = OK;
+
+ /* R3 OCR (48-bit)
+ * 47 0 Start bit
+ * 46 0 Transmission bit (0=from card)
+ * 45:40 bit5 - bit0 Reserved
+ * 39:8 bit31 - bit0 32-bit OCR register
+ * 7:1 bit6 - bit0 Reserved
+ * 0 1 End bit
+ */
+
+ /* Check that this is the correct response to this command */
+
+#ifdef CONFIG_DEBUG
+ if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R3_RESPONSE &&
+ (cmd & MMCSD_RESPONSE_MASK) != MMCSD_R7_RESPONSE)
+ {
+ fdbg("ERROR: Wrong response CMD=%08x\n", cmd);
+ ret = -EINVAL;
+ }
+ else
+#endif
+ {
+ /* Check if a timeout occurred (Apparently a CRC error can terminate
+ * a good response)
+ */
+
+ regval = getreg32(STM32_SDIO_STA);
+ if (regval & SDIO_STA_CTIMEOUT)
+ {
+ fdbg("ERROR: Timeout STA: %08x\n", regval);
+ ret = -ETIMEDOUT;
+ }
+ }
+
+ putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
+ if (rshort)
+ {
+ *rshort = getreg32(STM32_SDIO_RESP1);
+ }
+ return ret;
+}
+
+/* MMC responses not supported */
+
+static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rnotimpl)
+{
+ putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
+ return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: stm32_waitenable
+ *
+ * Description:
+ * Enable/disable of a set of SDIO wait events. This is part of the
+ * the SDIO_WAITEVENT sequence. The set of to-be-waited-for events is
+ * configured before calling stm32_eventwait. This is done in this way
+ * to help the driver to eliminate race conditions between the command
+ * setup and the subsequent events.
+ *
+ * The enabled events persist until either (1) SDIO_WAITENABLE is called
+ * again specifying a different set of wait events, or (2) SDIO_EVENTWAIT
+ * returns.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * eventset - A bitset of events to enable or disable (see SDIOWAIT_*
+ * definitions). 0=disable; 1=enable.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_waitenable(FAR struct sdio_dev_s *dev,
+ sdio_eventset_t eventset)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
+ uint32_t waitmask;
+
+ DEBUGASSERT(priv != NULL);
+
+ /* Disable event-related interrupts */
+
+ stm32_configwaitints(priv, 0, 0, 0);
+
+ /* Select the interrupt mask that will give us the appropriate wakeup
+ * interrupts.
+ */
+
+ waitmask = 0;
+ if ((eventset & SDIOWAIT_CMDDONE) != 0)
+ {
+ waitmask |= SDIO_CMDDONE_MASK;
+ }
+
+ if ((eventset & SDIOWAIT_RESPONSEDONE) != 0)
+ {
+ waitmask |= SDIO_RESPDONE_MASK;
+ }
+
+ if ((eventset & SDIOWAIT_TRANSFERDONE) != 0)
+ {
+ waitmask |= SDIO_XFRDONE_MASK;
+ }
+
+ /* Enable event-related interrupts */
+
+ putreg32(SDIO_WAITALL_ICR, STM32_SDIO_ICR);
+ stm32_configwaitints(priv, waitmask, eventset, 0);
+}
+
+/****************************************************************************
+ * Name: stm32_eventwait
+ *
+ * Description:
+ * Wait for one of the enabled events to occur (or a timeout). Note that
+ * all events enabled by SDIO_WAITEVENTS are disabled when stm32_eventwait
+ * returns. SDIO_WAITEVENTS must be called again before stm32_eventwait
+ * can be used again.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * timeout - Maximum time in milliseconds to wait. Zero means immediate
+ * timeout with no wait. The timeout value is ignored if
+ * SDIOWAIT_TIMEOUT is not included in the waited-for eventset.
+ *
+ * Returned Value:
+ * Event set containing the event(s) that ended the wait. Should always
+ * be non-zero. All events are disabled after the wait concludes.
+ *
+ ****************************************************************************/
+
+static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev,
+ uint32_t timeout)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
+ sdio_eventset_t wkupevent = 0;
+ irqstate_t flags;
+ int ret;
+
+ /* There is a race condition here... the event may have completed before
+ * we get here. In this case waitevents will be zero, but wkupevents will
+ * be non-zero (and, hopefully, the semaphore count will also be non-zero.
+ */
+
+ flags = irqsave();
+ DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
+
+ /* Check if the timeout event is specified in the event set */
+
+ if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
+ {
+ int delay;
+
+ /* Yes.. Handle a cornercase: The user request a timeout event but
+ * with timeout == 0?
+ */
+
+ if (!timeout)
+ {
+ /* Then just tell the caller that we already timed out */
+
+ wkupevent = SDIOWAIT_TIMEOUT;
+ goto errout;
+ }
+
+ /* Start the watchdog timer */
+
+ delay = (timeout + (MSEC_PER_TICK-1)) / MSEC_PER_TICK;
+ ret = wd_start(priv->waitwdog, delay, (wdentry_t)stm32_eventtimeout,
+ 1, (uint32_t)priv);
+ if (ret != OK)
+ {
+ fdbg("ERROR: wd_start failed: %d\n", ret);
+ }
+ }
+
+ /* Loop until the event (or the timeout occurs). Race conditions are avoided
+ * by calling stm32_waitenable prior to triggering the logic that will cause
+ * the wait to terminate. Under certain race conditions, the waited-for
+ * may have already occurred before this function was called!
+ */
+
+ for (;;)
+ {
+ /* Wait for an event in event set to occur. If this the event has already
+ * occurred, then the semaphore will already have been incremented and
+ * there will be no wait.
+ */
+
+ stm32_takesem(priv);
+ wkupevent = priv->wkupevent;
+
+ /* Check if the event has occurred. When the event has occurred, then
+ * evenset will be set to 0 and wkupevent will be set to a nonzero value.
+ */
+
+ if (wkupevent != 0)
+ {
+ /* Yes... break out of the loop with wkupevent non-zero */
+
+ break;
+ }
+ }
+
+ /* Disable event-related interrupts */
+
+ stm32_configwaitints(priv, 0, 0, 0);
+#ifdef CONFIG_SDIO_DMA
+ priv->xfrflags = 0;
+#endif
+
+errout:
+ irqrestore(flags);
+ stm32_dumpsamples(priv);
+ return wkupevent;
+}
+
+/****************************************************************************
+ * Name: stm32_callbackenable
+ *
+ * Description:
+ * Enable/disable of a set of SDIO callback events. This is part of the
+ * the SDIO callback sequence. The set of events is configured to enabled
+ * callbacks to the function provided in stm32_registercallback.
+ *
+ * Events are automatically disabled once the callback is performed and no
+ * further callback events will occur until they are again enabled by
+ * calling this methos.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * eventset - A bitset of events to enable or disable (see SDIOMEDIA_*
+ * definitions). 0=disable; 1=enable.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void stm32_callbackenable(FAR struct sdio_dev_s *dev,
+ sdio_eventset_t eventset)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
+
+ fvdbg("eventset: %02x\n", eventset);
+ DEBUGASSERT(priv != NULL);
+
+ priv->cbevents = eventset;
+ stm32_callback(priv);
+}
+
+/****************************************************************************
+ * Name: stm32_registercallback
+ *
+ * Description:
+ * Register a callback that that will be invoked on any media status
+ * change. Callbacks should not be made from interrupt handlers, rather
+ * interrupt level events should be handled by calling back on the work
+ * thread.
+ *
+ * When this method is called, all callbacks should be disabled until they
+ * are enabled via a call to SDIO_CALLBACKENABLE
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * callback - The funtion to call on the media change
+ * arg - A caller provided value to return with the callback
+ *
+ * Returned Value:
+ * 0 on success; negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_registercallback(FAR struct sdio_dev_s *dev,
+ worker_t callback, void *arg)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
+
+ /* Disable callbacks and register this callback and is argument */
+
+ fvdbg("Register %p(%p)\n", callback, arg);
+ DEBUGASSERT(priv != NULL);
+
+ priv->cbevents = 0;
+ priv->cbarg = arg;
+ priv->callback = callback;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_dmasupported
+ *
+ * Description:
+ * Return true if the hardware can support DMA
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ * true if DMA is supported.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static bool stm32_dmasupported(FAR struct sdio_dev_s *dev)
+{
+ return true;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_dmarecvsetup
+ *
+ * Description:
+ * Setup to perform a read DMA. If the processor supports a data cache,
+ * then this method will also make sure that the contents of the DMA memory
+ * and the data cache are coherent. For read transfers this may mean
+ * invalidating the data cache.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * buffer - The memory to DMA from
+ * buflen - The size of the DMA transfer in bytes
+ *
+ * Returned Value:
+ * OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
+ size_t buflen)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ uint32_t dblocksize;
+ int ret = -EINVAL;
+
+ DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
+ DEBUGASSERT(((uint32_t)buffer & 3) == 0);
+
+ /* Reset the DPSM configuration */
+
+ stm32_datadisable();
+
+ /* Wide bus operation is required for DMA */
+
+ if (priv->widebus)
+ {
+ stm32_sampleinit();
+ stm32_sample(priv, SAMPLENDX_BEFORE_SETUP);
+
+ /* Save the destination buffer information for use by the interrupt handler */
+
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = buflen;
+ priv->dmamode = true;
+
+ /* Then set up the SDIO data path */
+
+ dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
+ stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize|SDIO_DCTRL_DTDIR);
+
+ /* Configure the RX DMA */
+
+ stm32_configxfrints(priv, SDIO_DMARECV_MASK);
+
+ putreg32(1, SDIO_DCTRL_DMAEN_BB);
+ stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32_t)buffer,
+ (buflen + 3) >> 2, SDIO_RXDMA32_CONFIG);
+
+ /* Start the DMA */
+
+ stm32_sample(priv, SAMPLENDX_BEFORE_ENABLE);
+ stm32_dmastart(priv->dma, stm32_dmacallback, priv, false);
+ stm32_sample(priv, SAMPLENDX_AFTER_SETUP);
+ ret = OK;
+ }
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_dmasendsetup
+ *
+ * Description:
+ * Setup to perform a write DMA. If the processor supports a data cache,
+ * then this method will also make sure that the contents of the DMA memory
+ * and the data cache are coherent. For write transfers, this may mean
+ * flushing the data cache.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * buffer - The memory to DMA into
+ * buflen - The size of the DMA transfer in bytes
+ *
+ * Returned Value:
+ * OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
+ FAR const uint8_t *buffer, size_t buflen)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ uint32_t dblocksize;
+ int ret = -EINVAL;
+
+ DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
+ DEBUGASSERT(((uint32_t)buffer & 3) == 0);
+
+ /* Reset the DPSM configuration */
+
+ stm32_datadisable();
+
+ /* Wide bus operation is required for DMA */
+
+ if (priv->widebus)
+ {
+ stm32_sampleinit();
+ stm32_sample(priv, SAMPLENDX_BEFORE_SETUP);
+
+ /* Save the source buffer information for use by the interrupt handler */
+
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = buflen;
+ priv->dmamode = true;
+
+ /* Then set up the SDIO data path */
+
+ dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
+ stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize);
+
+ /* Configure the TX DMA */
+
+ stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32_t)buffer,
+ (buflen + 3) >> 2, SDIO_TXDMA32_CONFIG);
+
+ stm32_sample(priv, SAMPLENDX_BEFORE_ENABLE);
+ putreg32(1, SDIO_DCTRL_DMAEN_BB);
+
+ /* Start the DMA */
+
+ stm32_dmastart(priv->dma, stm32_dmacallback, priv, false);
+ stm32_sample(priv, SAMPLENDX_AFTER_SETUP);
+
+ /* Enable TX interrrupts */
+
+ stm32_configxfrints(priv, SDIO_DMASEND_MASK);
+
+ ret = OK;
+ }
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Initialization/uninitialization/reset
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_callback
+ *
+ * Description:
+ * Perform callback.
+ *
+ * Assumptions:
+ * This function does not execute in the context of an interrupt handler.
+ * It may be invoked on any user thread or scheduled on the work thread
+ * from an interrupt handler.
+ *
+ ****************************************************************************/
+
+static void stm32_callback(void *arg)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s*)arg;
+
+ /* Is a callback registered? */
+
+ DEBUGASSERT(priv != NULL);
+ fvdbg("Callback %p(%p) cbevents: %02x cdstatus: %02x\n",
+ priv->callback, priv->cbarg, priv->cbevents, priv->cdstatus);
+
+ if (priv->callback)
+ {
+ /* Yes.. Check for enabled callback events */
+
+ if ((priv->cdstatus & SDIO_STATUS_PRESENT) != 0)
+ {
+ /* Media is present. Is the media inserted event enabled? */
+
+ if ((priv->cbevents & SDIOMEDIA_INSERTED) == 0)
+ {
+ /* No... return without performing the callback */
+
+ return;
+ }
+ }
+ else
+ {
+ /* Media is not present. Is the media eject event enabled? */
+
+ if ((priv->cbevents & SDIOMEDIA_EJECTED) == 0)
+ {
+ /* No... return without performing the callback */
+
+ return;
+ }
+ }
+
+ /* Perform the callback, disabling further callbacks. Of course, the
+ * the callback can (and probably should) re-enable callbacks.
+ */
+
+ priv->cbevents = 0;
+
+ /* Callbacks cannot be performed in the context of an interrupt handler.
+ * If we are in an interrupt handler, then queue the callback to be
+ * performed later on the work thread.
+ */
+
+ if (up_interrupt_context())
+ {
+ /* Yes.. queue it */
+
+ fvdbg("Queuing callback to %p(%p)\n", priv->callback, priv->cbarg);
+ (void)work_queue(&priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
+ }
+ else
+ {
+ /* No.. then just call the callback here */
+
+ fvdbg("Callback to %p(%p)\n", priv->callback, priv->cbarg);
+ priv->callback(priv->cbarg);
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_default
+ *
+ * Description:
+ * Restore SDIO registers to their default, reset values
+ *
+ ****************************************************************************/
+
+static void stm32_default(void)
+{
+ putreg32(SDIO_POWER_RESET, STM32_SDIO_POWER);
+ putreg32(SDIO_CLKCR_RESET, STM32_SDIO_CLKCR);
+ putreg32(SDIO_ARG_RESET, STM32_SDIO_ARG);
+ putreg32(SDIO_CMD_RESET, STM32_SDIO_CMD);
+ putreg32(SDIO_DTIMER_RESET, STM32_SDIO_DTIMER);
+ putreg32(SDIO_DLEN_RESET, STM32_SDIO_DLEN);
+ putreg32(SDIO_DCTRL_RESET, STM32_SDIO_DCTRL);
+ putreg32(SDIO_ICR_RESET, STM32_SDIO_ICR);
+ putreg32(SDIO_MASK_RESET, STM32_SDIO_MASK);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sdio_initialize
+ *
+ * Description:
+ * Initialize SDIO for operation.
+ *
+ * Input Parameters:
+ * slotno - Not used.
+ *
+ * Returned Values:
+ * A reference to an SDIO interface structure. NULL is returned on failures.
+ *
+ ****************************************************************************/
+
+FAR struct sdio_dev_s *sdio_initialize(int slotno)
+{
+ /* There is only one slot */
+
+ struct stm32_dev_s *priv = &g_sdiodev;
+
+ /* Initialize the SDIO slot structure */
+
+ sem_init(&priv->waitsem, 0, 0);
+ priv->waitwdog = wd_create();
+ DEBUGASSERT(priv->waitwdog);
+
+ /* Allocate a DMA channel */
+
+#ifdef CONFIG_SDIO_DMA
+ priv->dma = stm32_dmachannel(SDIO_DMACHAN);
+ DEBUGASSERT(priv->dma);
+#endif
+
+ /* Configure GPIOs for 4-bit, wide-bus operation (the chip is capable of
+ * 8-bit wide bus operation but D4-D7 are not configured).
+ *
+ * If bus is multiplexed then there is a custom bus configuration utility
+ * in the scope of the board support package.
+ */
+
+#ifndef CONFIG_SDIO_MUXBUS
+ stm32_configgpio(GPIO_SDIO_D0);
+#ifndef CONFIG_SDIO_WIDTH_D1_ONLY
+ stm32_configgpio(GPIO_SDIO_D1);
+ stm32_configgpio(GPIO_SDIO_D2);
+ stm32_configgpio(GPIO_SDIO_D3);
+#endif
+ stm32_configgpio(GPIO_SDIO_CK);
+ stm32_configgpio(GPIO_SDIO_CMD);
+#endif
+
+ /* Reset the card and assure that it is in the initial, unconfigured
+ * state.
+ */
+
+ stm32_reset(&priv->dev);
+ return &g_sdiodev.dev;
+}
+
+/****************************************************************************
+ * Name: sdio_mediachange
+ *
+ * Description:
+ * Called by board-specific logic -- posssible from an interrupt handler --
+ * in order to signal to the driver that a card has been inserted or
+ * removed from the slot
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO driver device state structure.
+ * cardinslot - true is a card has been detected in the slot; false if a
+ * card has been removed from the slot. Only transitions
+ * (inserted->removed or removed->inserted should be reported)
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ uint8_t cdstatus;
+ irqstate_t flags;
+
+ /* Update card status */
+
+ flags = irqsave();
+ cdstatus = priv->cdstatus;
+ if (cardinslot)
+ {
+ priv->cdstatus |= SDIO_STATUS_PRESENT;
+ }
+ else
+ {
+ priv->cdstatus &= ~SDIO_STATUS_PRESENT;
+ }
+ fvdbg("cdstatus OLD: %02x NEW: %02x\n", cdstatus, priv->cdstatus);
+
+ /* Perform any requested callback if the status has changed */
+
+ if (cdstatus != priv->cdstatus)
+ {
+ stm32_callback(priv);
+ }
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: sdio_wrprotect
+ *
+ * Description:
+ * Called by board-specific logic to report if the card in the slot is
+ * mechanically write protected.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO driver device state structure.
+ * wrprotect - true is a card is writeprotected.
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ irqstate_t flags;
+
+ /* Update card status */
+
+ flags = irqsave();
+ if (wrprotect)
+ {
+ priv->cdstatus |= SDIO_STATUS_WRPROTECTED;
+ }
+ else
+ {
+ priv->cdstatus &= ~SDIO_STATUS_WRPROTECTED;
+ }
+ fvdbg("cdstatus: %02x\n", priv->cdstatus);
+ irqrestore(flags);
+}
+#endif /* CONFIG_STM32_SDIO */
diff --git a/nuttx/arch/arm/src/stm32/stm32_sdio.h b/nuttx/arch/arm/src/stm32/stm32_sdio.h
new file mode 100644
index 000000000..ceeb56f0d
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_sdio.h
@@ -0,0 +1,127 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_sdio.h
+ *
+ * Copyright (C) 2009, 2011 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_STM32_STM32_SDIO_H
+#define __ARCH_ARM_SRC_STM32_STM32_SDIO_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdbool.h>
+
+#include "chip.h"
+#include "chip/stm32_sdio.h"
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: sdio_initialize
+ *
+ * Description:
+ * Initialize SDIO for operation.
+ *
+ * Input Parameters:
+ * slotno - Not used.
+ *
+ * Returned Values:
+ * A reference to an SDIO interface structure. NULL is returned on failures.
+ *
+ ****************************************************************************/
+
+struct sdio_dev_s; /* See include/nuttx/sdio.h */
+EXTERN FAR struct sdio_dev_s *sdio_initialize(int slotno);
+
+/****************************************************************************
+ * Name: sdio_mediachange
+ *
+ * Description:
+ * Called by board-specific logic -- posssible from an interrupt handler --
+ * in order to signal to the driver that a card has been inserted or
+ * removed from the slot
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO driver device state structure.
+ * cardinslot - true is a card has been detected in the slot; false if a
+ * card has been removed from the slot. Only transitions
+ * (inserted->removed or removed->inserted should be reported)
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+EXTERN void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot);
+
+/****************************************************************************
+ * Name: sdio_wrprotect
+ *
+ * Description:
+ * Called by board-specific logic to report if the card in the slot is
+ * mechanically write protected.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO driver device state structure.
+ * wrprotect - true is a card is writeprotected.
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+EXTERN void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_SDIO_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_serial.c b/nuttx/arch/arm/src/stm32/stm32_serial.c
new file mode 100644
index 000000000..01c519b39
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_serial.c
@@ -0,0 +1,1959 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_serial.c
+ *
+ * Copyright (C) 2009-2012 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 <nuttx/power/pm.h>
+
+#ifdef CONFIG_SERIAL_TERMIOS
+# include <termios.h>
+#endif
+
+#include <arch/serial.h>
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "stm32_uart.h"
+#include "stm32_dma.h"
+#include "up_arch.h"
+#include "up_internal.h"
+#include "os_internal.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+/* Some sanity checks *******************************************************/
+/* DMA configuration */
+
+/* If DMA is enabled on any USART, then very that other pre-requisites
+ * have also been selected.
+ */
+
+#if SERIAL_HAVE_DMA
+
+/* Verify that DMA has been enabled an the DMA channel has been defined.
+ * NOTE: These assignments may only be true for the F4.
+ */
+
+# if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART6_RXDMA)
+# ifndef CONFIG_STM32_DMA2
+# error STM32 USART1/6 receive DMA requires CONFIG_STM32_DMA2
+# endif
+# endif
+
+# if defined(CONFIG_USART2_RXDMA) || defined(CONFIG_USART3_RXDMA) || \
+ defined(CONFIG_USART4_RXDMA) || defined(CONFIG_USART5_RXDMA)
+# ifndef CONFIG_STM32_DMA1
+# error STM32 USART2/3/4/5 receive DMA requires CONFIG_STM32_DMA1
+# endif
+# endif
+
+/* For the F4, there are alternate DMA channels for USART1 and 6.
+ * Logic in the board.h file make the DMA channel selection by defining
+ * the following in the board.h file.
+ */
+
+# if defined(CONFIG_USART1_RXDMA) && !defined(DMAMAP_USART1_RX)
+# error "USART1 DMA channel not defined (DMAMAP_USART1_RX)"
+# endif
+
+# if defined(CONFIG_USART2_RXDMA) && !defined(DMAMAP_USART2_RX)
+# error "USART2 DMA channel not defined (DMAMAP_USART2_RX)"
+# endif
+
+# if defined(CONFIG_USART3_RXDMA) && !defined(DMAMAP_USART3_RX)
+# error "USART3 DMA channel not defined (DMAMAP_USART3_RX)"
+# endif
+
+# if defined(CONFIG_USART4_RXDMA) && !defined(DMAMAP_UART4_RX)
+# error "UART4 DMA channel not defined (DMAMAP_UART4_RX)"
+# endif
+
+# if defined(CONFIG_USART5_RXDMA) && !defined(DMAMAP_UART5_RX)
+# error "UART5 DMA channel not defined (DMAMAP_UART5_RX)"
+# endif
+
+# if defined(CONFIG_USART6_RXDMA) && !defined(DMAMAP_USART6_RX)
+# error "USART6 DMA channel not defined (DMAMAP_USART6_RX)"
+# endif
+
+/* The DMA buffer size when using RX DMA to emulate a FIFO.
+ *
+ * When streaming data, the generic serial layer will be called
+ * everytime the FIFO receives half this number of bytes.
+ */
+
+# define RXDMA_BUFFER_SIZE 32
+#endif
+
+/* Power management definitions */
+
+#if defined(CONFIG_PM) && !defined(CONFIG_PM_SERIAL_ACTIVITY)
+# define CONFIG_PM_SERIAL_ACTIVITY 10
+#endif
+
+#ifdef USE_SERIALDRIVER
+#ifdef HAVE_UART
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct up_dev_s
+{
+ struct uart_dev_s dev; /* Generic UART device */
+ uint16_t ie; /* Saved interrupt mask bits value */
+ uint16_t sr; /* Saved status bits */
+
+ /* If termios are supported, then the following fields may vary at
+ * runtime.
+ */
+
+#ifdef CONFIG_SERIAL_TERMIOS
+ uint8_t parity; /* 0=none, 1=odd, 2=even */
+ uint8_t bits; /* Number of bits (7 or 8) */
+ bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */
+ uint32_t baud; /* Configured baud */
+#else
+ const uint8_t parity; /* 0=none, 1=odd, 2=even */
+ const uint8_t bits; /* Number of bits (7 or 8) */
+ const bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */
+ const uint32_t baud; /* Configured baud */
+#endif
+
+ const uint8_t irq; /* IRQ associated with this USART */
+ const uint32_t apbclock; /* PCLK 1 or 2 frequency */
+ const uint32_t usartbase; /* Base address of USART registers */
+ const uint32_t tx_gpio; /* U[S]ART TX GPIO pin configuration */
+ const uint32_t rx_gpio; /* U[S]ART RX GPIO pin configuration */
+ const uint32_t rts_gpio; /* U[S]ART RTS GPIO pin configuration */
+ const uint32_t cts_gpio; /* U[S]ART CTS GPIO pin configuration */
+
+#ifdef SERIAL_HAVE_DMA
+ const unsigned int rxdma_channel; /* DMA channel assigned */
+#endif
+
+ int (* const vector)(int irq, void *context); /* Interrupt handler */
+
+ /* RX DMA state */
+
+#ifdef SERIAL_HAVE_DMA
+ DMA_HANDLE rxdma; /* currently-open receive DMA stream */
+ bool rxenable; /* DMA-based reception en/disable */
+ uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
+ char *const rxfifo; /* Receive DMA buffer */
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void up_setspeed(struct uart_dev_s *dev);
+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_common(struct up_dev_s *dev);
+static int up_ioctl(struct file *filep, int cmd, unsigned long arg);
+#ifndef SERIAL_HAVE_ONLY_DMA
+static int up_receive(struct uart_dev_s *dev, uint32_t *status);
+static void up_rxint(struct uart_dev_s *dev, bool enable);
+static bool up_rxavailable(struct uart_dev_s *dev);
+#endif
+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);
+
+#ifdef SERIAL_HAVE_DMA
+static int up_dma_setup(struct uart_dev_s *dev);
+static void up_dma_shutdown(struct uart_dev_s *dev);
+static int up_dma_receive(struct uart_dev_s *dev, uint32_t *status);
+static void up_dma_rxint(struct uart_dev_s *dev, bool enable);
+static bool up_dma_rxavailable(struct uart_dev_s *dev);
+
+static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, void *arg);
+#endif
+
+#ifdef CONFIG_PM
+static void up_pm_notify(struct pm_callback_s *cb, enum pm_state_e pmstate);
+static int up_pm_prepare(struct pm_callback_s *cb, enum pm_state_e pmstate);
+#endif
+
+#ifdef CONFIG_STM32_USART1
+static int up_interrupt_usart1(int irq, void *context);
+#endif
+#ifdef CONFIG_STM32_USART2
+static int up_interrupt_usart2(int irq, void *context);
+#endif
+#ifdef CONFIG_STM32_USART3
+static int up_interrupt_usart3(int irq, void *context);
+#endif
+#ifdef CONFIG_STM32_UART4
+static int up_interrupt_uart4(int irq, void *context);
+#endif
+#ifdef CONFIG_STM32_UART5
+static int up_interrupt_uart5(int irq, void *context);
+#endif
+#ifdef CONFIG_STM32_USART6
+static int up_interrupt_usart6(int irq, void *context);
+#endif
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+#ifndef SERIAL_HAVE_ONLY_DMA
+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,
+ .send = up_send,
+ .txint = up_txint,
+ .txready = up_txready,
+ .txempty = up_txready,
+};
+#endif
+
+#ifdef SERIAL_HAVE_DMA
+static const struct uart_ops_s g_uart_dma_ops =
+{
+ .setup = up_dma_setup,
+ .shutdown = up_dma_shutdown,
+ .attach = up_attach,
+ .detach = up_detach,
+ .ioctl = up_ioctl,
+ .receive = up_dma_receive,
+ .rxint = up_dma_rxint,
+ .rxavailable = up_dma_rxavailable,
+ .send = up_send,
+ .txint = up_txint,
+ .txready = up_txready,
+ .txempty = up_txready,
+};
+#endif
+
+/* I/O buffers */
+
+#ifdef CONFIG_STM32_USART1
+static char g_usart1rxbuffer[CONFIG_USART1_RXBUFSIZE];
+static char g_usart1txbuffer[CONFIG_USART1_TXBUFSIZE];
+# ifdef CONFIG_USART1_RXDMA
+static char g_usart1rxfifo[RXDMA_BUFFER_SIZE];
+# endif
+#endif
+
+#ifdef CONFIG_STM32_USART2
+static char g_usart2rxbuffer[CONFIG_USART2_RXBUFSIZE];
+static char g_usart2txbuffer[CONFIG_USART2_TXBUFSIZE];
+# ifdef CONFIG_USART2_RXDMA
+static char g_usart2rxfifo[RXDMA_BUFFER_SIZE];
+# endif
+#endif
+
+#ifdef CONFIG_STM32_USART3
+static char g_usart3rxbuffer[CONFIG_USART3_RXBUFSIZE];
+static char g_usart3txbuffer[CONFIG_USART3_TXBUFSIZE];
+# ifdef CONFIG_USART3_RXDMA
+static char g_usart3rxfifo[RXDMA_BUFFER_SIZE];
+# endif
+#endif
+
+#ifdef CONFIG_STM32_UART4
+static char g_uart4rxbuffer[CONFIG_USART4_RXBUFSIZE];
+static char g_uart4txbuffer[CONFIG_USART4_TXBUFSIZE];
+# ifdef CONFIG_USART4_RXDMA
+static char g_uart4rxfifo[RXDMA_BUFFER_SIZE];
+# endif
+#endif
+
+#ifdef CONFIG_STM32_UART5
+static char g_uart5rxbuffer[CONFIG_USART5_RXBUFSIZE];
+static char g_uart5txbuffer[CONFIG_USART5_TXBUFSIZE];
+# ifdef CONFIG_USART5_RXDMA
+static char g_uart5rxfifo[RXDMA_BUFFER_SIZE];
+# endif
+#endif
+
+#ifdef CONFIG_STM32_USART6
+static char g_usart6rxbuffer[CONFIG_USART6_RXBUFSIZE];
+static char g_usart6txbuffer[CONFIG_USART6_TXBUFSIZE];
+# ifdef CONFIG_USART6_RXDMA
+static char g_usart6rxfifo[RXDMA_BUFFER_SIZE];
+# endif
+#endif
+
+/* This describes the state of the STM32 USART1 ports. */
+
+#ifdef CONFIG_STM32_USART1
+static struct up_dev_s g_usart1priv =
+{
+ .dev =
+ {
+#if CONSOLE_UART == 1
+ .isconsole = true,
+#endif
+ .recv =
+ {
+ .size = CONFIG_USART1_RXBUFSIZE,
+ .buffer = g_usart1rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART1_TXBUFSIZE,
+ .buffer = g_usart1txbuffer,
+ },
+#ifdef CONFIG_USART1_RXDMA
+ .ops = &g_uart_dma_ops,
+#else
+ .ops = &g_uart_ops,
+#endif
+ .priv = &g_usart1priv,
+ },
+
+ .irq = STM32_IRQ_USART1,
+ .parity = CONFIG_USART1_PARITY,
+ .bits = CONFIG_USART1_BITS,
+ .stopbits2 = CONFIG_USART1_2STOP,
+ .baud = CONFIG_USART1_BAUD,
+ .apbclock = STM32_PCLK2_FREQUENCY,
+ .usartbase = STM32_USART1_BASE,
+ .tx_gpio = GPIO_USART1_TX,
+ .rx_gpio = GPIO_USART1_RX,
+#ifdef GPIO_USART1_CTS
+ .cts_gpio = GPIO_USART1_CTS,
+#endif
+#ifdef GPIO_USART1_RTS
+ .rts_gpio = GPIO_USART1_RTS,
+#endif
+#ifdef CONFIG_USART1_RXDMA
+ .rxdma_channel = DMAMAP_USART1_RX,
+ .rxfifo = g_usart1rxfifo,
+#endif
+ .vector = up_interrupt_usart1,
+};
+#endif
+
+/* This describes the state of the STM32 USART2 port. */
+
+#ifdef CONFIG_STM32_USART2
+static struct up_dev_s g_usart2priv =
+{
+ .dev =
+ {
+#if CONSOLE_UART == 2
+ .isconsole = true,
+#endif
+ .recv =
+ {
+ .size = CONFIG_USART2_RXBUFSIZE,
+ .buffer = g_usart2rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART2_TXBUFSIZE,
+ .buffer = g_usart2txbuffer,
+ },
+#ifdef CONFIG_USART2_RXDMA
+ .ops = &g_uart_dma_ops,
+#else
+ .ops = &g_uart_ops,
+#endif
+ .priv = &g_usart2priv,
+ },
+
+ .irq = STM32_IRQ_USART2,
+ .parity = CONFIG_USART2_PARITY,
+ .bits = CONFIG_USART2_BITS,
+ .stopbits2 = CONFIG_USART2_2STOP,
+ .baud = CONFIG_USART2_BAUD,
+ .apbclock = STM32_PCLK1_FREQUENCY,
+ .usartbase = STM32_USART2_BASE,
+ .tx_gpio = GPIO_USART2_TX,
+ .rx_gpio = GPIO_USART2_RX,
+#ifdef GPIO_USART2_CTS
+ .cts_gpio = GPIO_USART2_CTS,
+#endif
+#ifdef GPIO_USART2_RTS
+ .rts_gpio = GPIO_USART2_RTS,
+#endif
+#ifdef CONFIG_USART2_RXDMA
+ .rxdma_channel = DMAMAP_USART2_RX,
+ .rxfifo = g_usart2rxfifo,
+#endif
+ .vector = up_interrupt_usart2,
+};
+#endif
+
+/* This describes the state of the STM32 USART3 port. */
+
+#ifdef CONFIG_STM32_USART3
+static struct up_dev_s g_usart3priv =
+{
+ .dev =
+ {
+#if CONSOLE_UART == 3
+ .isconsole = true,
+#endif
+ .recv =
+ {
+ .size = CONFIG_USART3_RXBUFSIZE,
+ .buffer = g_usart3rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART3_TXBUFSIZE,
+ .buffer = g_usart3txbuffer,
+ },
+#ifdef CONFIG_USART3_RXDMA
+ .ops = &g_uart_dma_ops,
+#else
+ .ops = &g_uart_ops,
+#endif
+ .priv = &g_usart3priv,
+ },
+
+ .irq = STM32_IRQ_USART3,
+ .parity = CONFIG_USART3_PARITY,
+ .bits = CONFIG_USART3_BITS,
+ .stopbits2 = CONFIG_USART3_2STOP,
+ .baud = CONFIG_USART3_BAUD,
+ .apbclock = STM32_PCLK1_FREQUENCY,
+ .usartbase = STM32_USART3_BASE,
+ .tx_gpio = GPIO_USART3_TX,
+ .rx_gpio = GPIO_USART3_RX,
+#ifdef GPIO_USART3_CTS
+ .cts_gpio = GPIO_USART3_CTS,
+#endif
+#ifdef GPIO_USART3_RTS
+ .rts_gpio = GPIO_USART3_RTS,
+#endif
+#ifdef CONFIG_USART3_RXDMA
+ .rxdma_channel = DMAMAP_USART3_RX,
+ .rxfifo = g_usart3rxfifo,
+#endif
+ .vector = up_interrupt_usart3,
+};
+#endif
+
+/* This describes the state of the STM32 UART4 port. */
+
+#ifdef CONFIG_STM32_UART4
+static struct up_dev_s g_uart4priv =
+{
+ .dev =
+ {
+#if CONSOLE_UART == 4
+ .isconsole = true,
+#endif
+ .recv =
+ {
+ .size = CONFIG_USART4_RXBUFSIZE,
+ .buffer = g_uart4rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART4_TXBUFSIZE,
+ .buffer = g_uart4txbuffer,
+ },
+#ifdef CONFIG_USART4_RXDMA
+ .ops = &g_uart_dma_ops,
+#else
+ .ops = &g_uart_ops,
+#endif
+ .priv = &g_uart4priv,
+ },
+
+ .irq = STM32_IRQ_UART4,
+ .parity = CONFIG_USART4_PARITY,
+ .bits = CONFIG_USART4_BITS,
+ .stopbits2 = CONFIG_USART4_2STOP,
+ .baud = CONFIG_USART4_BAUD,
+ .apbclock = STM32_PCLK1_FREQUENCY,
+ .usartbase = STM32_UART4_BASE,
+ .tx_gpio = GPIO_UART4_TX,
+ .rx_gpio = GPIO_UART4_RX,
+#ifdef GPIO_USART4_CTS
+ .cts_gpio = GPIO_UART4_CTS,
+#endif
+#ifdef GPIO_USART4_RTS
+ .rts_gpio = GPIO_UART4_RTS,
+#endif
+#ifdef CONFIG_USART4_RXDMA
+ .rxdma_channel = DMAMAP_UART4_RX,
+ .rxfifo = g_uart4rxfifo,
+#endif
+ .vector = up_interrupt_uart4,
+};
+#endif
+
+/* This describes the state of the STM32 UART5 port. */
+
+#ifdef CONFIG_STM32_UART5
+static struct up_dev_s g_uart5priv =
+{
+ .dev =
+ {
+#if CONSOLE_UART == 5
+ .isconsole = true,
+#endif
+ .recv =
+ {
+ .size = CONFIG_USART5_RXBUFSIZE,
+ .buffer = g_uart5rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART5_TXBUFSIZE,
+ .buffer = g_uart5txbuffer,
+ },
+#ifdef CONFIG_USART5_RXDMA
+ .ops = &g_uart_dma_ops,
+#else
+ .ops = &g_uart_ops,
+#endif
+ .priv = &g_uart5priv,
+ },
+
+ .irq = STM32_IRQ_UART5,
+ .parity = CONFIG_USART5_PARITY,
+ .bits = CONFIG_USART5_BITS,
+ .stopbits2 = CONFIG_USART5_2STOP,
+ .baud = CONFIG_USART5_BAUD,
+ .apbclock = STM32_PCLK1_FREQUENCY,
+ .usartbase = STM32_UART5_BASE,
+ .tx_gpio = GPIO_UART5_TX,
+ .rx_gpio = GPIO_UART5_RX,
+#ifdef GPIO_USART5_CTS
+ .cts_gpio = GPIO_UART5_CTS,
+#endif
+#ifdef GPIO_USART5_RTS
+ .rts_gpio = GPIO_UART5_RTS,
+#endif
+#ifdef CONFIG_USART5_RXDMA
+ .rxdma_channel = DMAMAP_UART5_RX,
+ .rxfifo = g_uart5rxfifo,
+#endif
+ .vector = up_interrupt_uart5,
+};
+#endif
+
+/* This describes the state of the STM32 USART6 port. */
+
+#ifdef CONFIG_STM32_USART6
+static struct up_dev_s g_usart6priv =
+{
+ .dev =
+ {
+#if CONSOLE_UART == 6
+ .isconsole = true,
+#endif
+ .recv =
+ {
+ .size = CONFIG_USART6_RXBUFSIZE,
+ .buffer = g_usart6rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART6_TXBUFSIZE,
+ .buffer = g_usart6txbuffer,
+ },
+#ifdef CONFIG_USART6_RXDMA
+ .ops = &g_uart_dma_ops,
+#else
+ .ops = &g_uart_ops,
+#endif
+ .priv = &g_usart6priv,
+ },
+
+ .irq = STM32_IRQ_USART6,
+ .parity = CONFIG_USART6_PARITY,
+ .bits = CONFIG_USART6_BITS,
+ .stopbits2 = CONFIG_USART6_2STOP,
+ .baud = CONFIG_USART6_BAUD,
+ .apbclock = STM32_PCLK2_FREQUENCY,
+ .usartbase = STM32_USART6_BASE,
+ .tx_gpio = GPIO_USART6_TX,
+ .rx_gpio = GPIO_USART6_RX,
+#ifdef GPIO_USART6_CTS
+ .cts_gpio = GPIO_USART6_CTS,
+#endif
+#ifdef GPIO_USART6_RTS
+ .rts_gpio = GPIO_USART6_RTS,
+#endif
+#ifdef CONFIG_USART6_RXDMA
+ .rxdma_channel = DMAMAP_USART6_RX,
+ .rxfifo = g_usart6rxfifo,
+#endif
+ .vector = up_interrupt_usart6,
+};
+#endif
+
+/* This table lets us iterate over the configured USARTs */
+
+static struct up_dev_s *uart_devs[STM32_NUSART] =
+{
+#ifdef CONFIG_STM32_USART1
+ [0] = &g_usart1priv,
+#endif
+#ifdef CONFIG_STM32_USART2
+ [1] = &g_usart2priv,
+#endif
+#ifdef CONFIG_STM32_USART3
+ [2] = &g_usart3priv,
+#endif
+#ifdef CONFIG_STM32_UART4
+ [3] = &g_uart4priv,
+#endif
+#ifdef CONFIG_STM32_UART5
+ [4] = &g_uart5priv,
+#endif
+#ifdef CONFIG_STM32_USART6
+ [5] = &g_usart6priv,
+#endif
+};
+
+#ifdef CONFIG_PM
+static struct pm_callback_s g_serialcb =
+{
+ .notify = up_pm_notify,
+ .prepare = up_pm_prepare,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_serialin
+ ****************************************************************************/
+
+static inline uint32_t up_serialin(struct up_dev_s *priv, int offset)
+{
+ return getreg32(priv->usartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_serialout
+ ****************************************************************************/
+
+static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t value)
+{
+ putreg32(value, priv->usartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_restoreusartint
+ ****************************************************************************/
+
+static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
+{
+ uint32_t cr;
+
+ /* Save the interrupt mask */
+
+ priv->ie = ie;
+
+ /* And restore the interrupt state (see the interrupt enable/usage table above) */
+
+ cr = up_serialin(priv, STM32_USART_CR1_OFFSET);
+ cr &= ~(USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE);
+ cr |= (ie & (USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE));
+ up_serialout(priv, STM32_USART_CR1_OFFSET, cr);
+
+ cr = up_serialin(priv, STM32_USART_CR3_OFFSET);
+ cr &= ~USART_CR3_EIE;
+ cr |= (ie & USART_CR3_EIE);
+ up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
+}
+
+/****************************************************************************
+ * Name: up_disableusartint
+ ****************************************************************************/
+
+static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
+{
+ if (ie)
+ {
+ uint32_t cr1;
+ uint32_t cr3;
+
+ /* USART interrupts:
+ *
+ * Enable Bit Status Meaning Usage
+ * ------------------ --- --------------- ------------------------------ ----------
+ * USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used)
+ * USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read
+ * " " USART_SR_ORE Overrun Error Detected
+ * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used)
+ * USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty
+ * USART_CR1_PEIE 8 USART_SR_PE Parity Error
+ *
+ * USART_CR2_LBDIE 6 USART_SR_LBD Break Flag (not used)
+ * USART_CR3_EIE 0 USART_SR_FE Framing Error
+ * " " USART_SR_NE Noise Error
+ * " " USART_SR_ORE Overrun Error Detected
+ * USART_CR3_CTSIE 10 USART_SR_CTS CTS flag (not used)
+ */
+
+ cr1 = up_serialin(priv, STM32_USART_CR1_OFFSET);
+ cr3 = up_serialin(priv, STM32_USART_CR3_OFFSET);
+
+ /* Return the current interrupt mask value for the used interrupts. Notice
+ * that this depends on the fact that none of the used interrupt enable bits
+ * overlap. This logic would fail if we needed the break interrupt!
+ */
+
+ *ie = (cr1 & (USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE)) | (cr3 & USART_CR3_EIE);
+ }
+
+ /* Disable all interrupts */
+
+ up_restoreusartint(priv, 0);
+}
+
+/****************************************************************************
+ * Name: up_dma_nextrx
+ *
+ * Description:
+ * Returns the index into the RX FIFO where the DMA will place the next
+ * byte that it receives.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_DMA
+static int up_dma_nextrx(struct up_dev_s *priv)
+{
+ size_t dmaresidual;
+
+ dmaresidual = stm32_dmaresidual(priv->rxdma);
+
+ return (RXDMA_BUFFER_SIZE - (int)dmaresidual);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_setspeed
+ *
+ * Description:
+ * Set the serial line speed.
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_SUPPRESS_UART_CONFIG
+static void up_setspeed(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ uint32_t usartdiv32;
+ uint32_t mantissa;
+ uint32_t fraction;
+ uint32_t brr;
+
+ /* Configure the USART Baud Rate. The baud rate for the receiver and
+ * transmitter (Rx and Tx) are both set to the same value as programmed
+ * in the Mantissa and Fraction values of USARTDIV.
+ *
+ * baud = fCK / (16 * usartdiv)
+ * usartdiv = fCK / (16 * baud)
+ *
+ * Where fCK is the input clock to the peripheral (PCLK1 for USART2, 3, 4, 5
+ * or PCLK2 for USART1)
+ *
+ * First calculate (NOTE: all stand baud values are even so dividing by two
+ * does not lose precision):
+ *
+ * usartdiv32 = 32 * usartdiv = fCK / (baud/2)
+ */
+
+ usartdiv32 = priv->apbclock / (priv->baud >> 1);
+
+ /* The mantissa part is then */
+
+ mantissa = usartdiv32 >> 5;
+ brr = mantissa << USART_BRR_MANT_SHIFT;
+
+ /* The fractional remainder (with rounding) */
+
+ fraction = (usartdiv32 - (mantissa << 5) + 1) >> 1;
+ brr |= fraction << USART_BRR_FRAC_SHIFT;
+ up_serialout(priv, STM32_USART_BRR_OFFSET, brr);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_setup
+ *
+ * Description:
+ * Configure the USART baud, bits, parity, etc. This method is called the
+ * first time that the serial port is opened.
+ *
+ ****************************************************************************/
+
+static int up_setup(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+#ifndef CONFIG_SUPPRESS_UART_CONFIG
+ uint32_t regval;
+
+ /* Note: The logic here depends on the fact that that the USART module
+ * was enabled in stm32_lowsetup().
+ */
+
+ /* Configure pins for USART use */
+
+ stm32_configgpio(priv->tx_gpio);
+ stm32_configgpio(priv->rx_gpio);
+
+ if (priv->cts_gpio != 0)
+ {
+ stm32_configgpio(priv->cts_gpio);
+ }
+
+ if (priv->rts_gpio != 0)
+ {
+ stm32_configgpio(priv->rts_gpio);
+ }
+
+ /* Configure CR2 */
+ /* Clear STOP, CLKEN, CPOL, CPHA, LBCL, and interrupt enable bits */
+
+ regval = up_serialin(priv, STM32_USART_CR2_OFFSET);
+ regval &= ~(USART_CR2_STOP_MASK|USART_CR2_CLKEN|USART_CR2_CPOL|
+ USART_CR2_CPHA|USART_CR2_LBCL|USART_CR2_LBDIE);
+
+ /* Configure STOP bits */
+
+ if (priv->stopbits2)
+ {
+ regval |= USART_CR2_STOP2;
+ }
+ up_serialout(priv, STM32_USART_CR2_OFFSET, regval);
+
+ /* Configure CR1 */
+ /* Clear M, PCE, PS, TE, REm and all interrupt enable bits */
+
+ regval = up_serialin(priv, STM32_USART_CR1_OFFSET);
+ regval &= ~(USART_CR1_M|USART_CR1_PCE|USART_CR1_PS|USART_CR1_TE|
+ USART_CR1_RE|USART_CR1_ALLINTS);
+
+ /* Configure word length and parity mode */
+
+ if (priv->bits == 9) /* Default: 1 start, 8 data, n stop */
+ {
+ regval |= USART_CR1_M; /* 1 start, 9 data, n stop */
+ }
+
+ if (priv->parity == 1) /* Odd parity */
+ {
+ regval |= (USART_CR1_PCE|USART_CR1_PS);
+ }
+ else if (priv->parity == 2) /* Even parity */
+ {
+ regval |= USART_CR1_PCE;
+ }
+
+ up_serialout(priv, STM32_USART_CR1_OFFSET, regval);
+
+ /* Configure CR3 */
+ /* Clear CTSE, RTSE, and all interrupt enable bits */
+
+ regval = up_serialin(priv, STM32_USART_CR3_OFFSET);
+ regval &= ~(USART_CR3_CTSIE|USART_CR3_CTSE|USART_CR3_RTSE|USART_CR3_EIE);
+
+ /* Configure hardware flow control -- Not yet supported */
+
+ up_serialout(priv, STM32_USART_CR3_OFFSET, regval);
+
+ /* Configure the USART Baud Rate. */
+
+ up_setspeed(dev);
+
+ /* Enable Rx, Tx, and the USART */
+
+ regval = up_serialin(priv, STM32_USART_CR1_OFFSET);
+ regval |= (USART_CR1_UE|USART_CR1_TE|USART_CR1_RE);
+ up_serialout(priv, STM32_USART_CR1_OFFSET, regval);
+#endif
+
+ /* Set up the cached interrupt enables value */
+
+ priv->ie = 0;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_dma_setup
+ *
+ * Description:
+ * Configure the USART baud, bits, parity, etc. This method is called the
+ * first time that the serial port is opened.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_DMA
+static int up_dma_setup(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ int result;
+ uint32_t regval;
+
+ /* Do the basic UART setup first */
+
+ result = up_setup(dev);
+ if (result != OK)
+ {
+ return result;
+ }
+
+ /* Acquire the DMA channel. This should always succeed. */
+
+ priv->rxdma = stm32_dmachannel(priv->rxdma_channel);
+
+ /* Configure for circular DMA reception into the RX fifo */
+
+ stm32_dmasetup(priv->rxdma,
+ priv->usartbase + STM32_USART_DR_OFFSET,
+ (uint32_t)priv->rxfifo,
+ RXDMA_BUFFER_SIZE,
+ DMA_SCR_DIR_P2M |
+ DMA_SCR_CIRC |
+ DMA_SCR_MINC |
+ DMA_SCR_PSIZE_8BITS |
+ DMA_SCR_MSIZE_8BITS |
+ DMA_SCR_PBURST_SINGLE |
+ DMA_SCR_MBURST_SINGLE);
+
+ /* Reset our DMA shadow pointer to match the address just
+ * programmed above.
+ */
+
+ priv->rxdmanext = 0;
+
+ /* Enable receive DMA for the UART */
+
+ regval = up_serialin(priv, STM32_USART_CR3_OFFSET);
+ regval |= USART_CR3_DMAR;
+ up_serialout(priv, STM32_USART_CR3_OFFSET, regval);
+
+ /* Start the DMA channel, and arrange for callbacks at the half and
+ * full points in the FIFO. This ensures that we have half a FIFO
+ * worth of time to claim bytes before they are overwritten.
+ */
+
+ stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)priv, true);
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: up_shutdown
+ *
+ * Description:
+ * Disable the USART. 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*)dev->priv;
+ uint32_t regval;
+
+ /* Disable all interrupts */
+
+ up_disableusartint(priv, NULL);
+
+ /* Disable Rx, Tx, and the UART */
+
+ regval = up_serialin(priv, STM32_USART_CR1_OFFSET);
+ regval &= ~(USART_CR1_UE|USART_CR1_TE|USART_CR1_RE);
+ up_serialout(priv, STM32_USART_CR1_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: up_dma_shutdown
+ *
+ * Description:
+ * Disable the USART. This method is called when the serial
+ * port is closed
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_DMA
+static void up_dma_shutdown(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+
+ /* Perform the normal UART shutdown */
+
+ up_shutdown(dev);
+
+ /* Stop the DMA channel */
+
+ stm32_dmastop(priv->rxdma);
+
+ /* Release the DMA channel */
+
+ stm32_dmafree(priv->rxdma);
+ priv->rxdma = NULL;
+}
+#endif
+
+/****************************************************************************
+ * Name: up_attach
+ *
+ * Description:
+ * Configure the USART 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, priv->vector);
+ if (ret == OK)
+ {
+ /* Enable the interrupt (RX and TX interrupts are still disabled
+ * in the USART
+ */
+
+ up_enable_irq(priv->irq);
+ }
+ return ret;
+}
+
+/****************************************************************************
+ * Name: up_detach
+ *
+ * Description:
+ * Detach USART 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_common
+ *
+ * Description:
+ * This is the USART 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_common(struct up_dev_s *priv)
+{
+ int passes;
+ bool handled;
+
+ /* Report serial activity to the power management logic */
+
+#if defined(CONFIG_PM) && CONFIG_PM_SERIAL_ACTIVITY > 0
+ pm_activity(CONFIG_PM_SERIAL_ACTIVITY);
+#endif
+
+ /* Loop until there are no characters to be transferred or,
+ * until we have been looping for a long time.
+ */
+
+ handled = true;
+ for (passes = 0; passes < 256 && handled; passes++)
+ {
+ handled = false;
+
+ /* Get the masked USART status word. */
+
+ priv->sr = up_serialin(priv, STM32_USART_SR_OFFSET);
+
+ /* USART interrupts:
+ *
+ * Enable Bit Status Meaning Usage
+ * ------------------ --- --------------- ------------------------------- ----------
+ * USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used)
+ * USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read
+ * " " USART_SR_ORE Overrun Error Detected
+ * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used)
+ * USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty
+ * USART_CR1_PEIE 8 USART_SR_PE Parity Error
+ *
+ * USART_CR2_LBDIE 6 USART_SR_LBD Break Flag (not used)
+ * USART_CR3_EIE 0 USART_SR_FE Framing Error
+ * " " USART_SR_NE Noise Error
+ * " " USART_SR_ORE Overrun Error Detected
+ * USART_CR3_CTSIE 10 USART_SR_CTS CTS flag (not used)
+ *
+ * NOTE: Some of these status bits must be cleared by explicity writing zero
+ * to the SR register: USART_SR_CTS, USART_SR_LBD. Note of those are currently
+ * being used.
+ */
+
+ /* Handle incoming, receive bytes. */
+
+ if ((priv->sr & USART_SR_RXNE) != 0 && (priv->ie & USART_CR1_RXNEIE) != 0)
+ {
+ /* Received data ready... process incoming bytes. NOTE the check for
+ * RXNEIE: We cannot call uart_recvchards of RX interrupts are disabled.
+ */
+
+ uart_recvchars(&priv->dev);
+ handled = true;
+ }
+
+ /* We may still have to read from the DR register to clear any pending
+ * error conditions.
+ */
+
+ else if ((priv->sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE)) != 0)
+ {
+ /* If an error occurs, read from DR to clear the error (data has
+ * been lost). If ORE is set along with RXNE then it tells you
+ * that the byte *after* the one in the data register has been
+ * lost, but the data register value is correct. That case will
+ * be handled above if interrupts are enabled. Otherwise, that
+ * good byte will be lost.
+ */
+
+ (void)up_serialin(priv, STM32_USART_DR_OFFSET);
+ }
+
+ /* Handle outgoing, transmit bytes */
+
+ if ((priv->sr & USART_SR_TXE) != 0 && (priv->ie & USART_CR1_TXEIE) != 0)
+ {
+ /* Transmit data regiser empty ... process outgoing bytes */
+
+ uart_xmitchars(&priv->dev);
+ handled = true;
+ }
+ }
+ 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;
+#ifdef CONFIG_SERIAL_TERMIOS
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+#endif
+ int ret = OK;
+
+ switch (cmd)
+ {
+ 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;
+
+#ifdef CONFIG_SERIAL_TERMIOS
+ case TCGETS:
+ {
+ struct termios *termiosp = (struct termios*)arg;
+
+ if (!termiosp)
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ /* TODO: Other termios fields are not yet returned.
+ * Note that only cfsetospeed is not necessary because we have
+ * knowledge that only one speed is supported.
+ */
+
+ cfsetispeed(termiosp, priv->baud);
+ }
+ break;
+
+ case TCSETS:
+ {
+ struct termios *termiosp = (struct termios*)arg;
+
+ if (!termiosp)
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ /* TODO: Handle other termios settings.
+ * Note that only cfgetispeed is used besued we have knowledge
+ * that only one speed is supported.
+ */
+
+ priv->baud = cfgetispeed(termiosp);
+ up_setspeed(dev);
+ }
+ break;
+#endif
+
+#ifdef CONFIG_USART_BREAKS
+ case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
+ {
+ irqstate_t flags = irqsave();
+ uint32_t cr2 = up_serialin(priv, STM32_USART_CR2_OFFSET);
+ up_serialout(priv, STM32_USART_CR2_OFFSET, cr2 | USART_CR2_LINEN);
+ irqrestore(flags);
+ }
+ break;
+
+ case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
+ {
+ irqstate_t flags;
+ flags = irqsave();
+ uint32_t cr1 = up_serialin(priv, STM32_USART_CR2_OFFSET);
+ up_serialout(priv, STM32_USART_CR2_OFFSET, cr2 & ~USART_CR2_LINEN);
+ irqrestore(flags);
+ }
+ break;
+#endif
+
+ default:
+ ret = -ENOTTY;
+ break;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: up_receive
+ *
+ * Description:
+ * Called (usually) from the interrupt level to receive one
+ * character from the USART. Error bits associated with the
+ * receipt are provided in the return 'status'.
+ *
+ ****************************************************************************/
+
+#ifndef SERIAL_HAVE_ONLY_DMA
+static int up_receive(struct uart_dev_s *dev, uint32_t *status)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ uint32_t dr;
+
+ /* Get the Rx byte */
+
+ dr = up_serialin(priv, STM32_USART_DR_OFFSET);
+
+ /* Get the Rx byte plux error information. Return those in status */
+
+ *status = priv->sr << 16 | dr;
+ priv->sr = 0;
+
+ /* Then return the actual received byte */
+
+ return dr & 0xff;
+}
+#endif
+
+/****************************************************************************
+ * Name: up_rxint
+ *
+ * Description:
+ * Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+#ifndef SERIAL_HAVE_ONLY_DMA
+static void up_rxint(struct uart_dev_s *dev, bool enable)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ irqstate_t flags;
+ uint16_t ie;
+
+ /* USART receive interrupts:
+ *
+ * Enable Bit Status Meaning Usage
+ * ------------------ --- --------------- ------------------------------- ----------
+ * USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used)
+ * USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read
+ * " " USART_SR_ORE Overrun Error Detected
+ * USART_CR1_PEIE 8 USART_SR_PE Parity Error
+ *
+ * USART_CR2_LBDIE 6 USART_SR_LBD Break Flag (not used)
+ * USART_CR3_EIE 0 USART_SR_FE Framing Error
+ * " " USART_SR_NE Noise Error
+ * " " USART_SR_ORE Overrun Error Detected
+ */
+
+ flags = irqsave();
+ ie = priv->ie;
+ if (enable)
+ {
+ /* Receive an interrupt when their is anything in the Rx data register (or an Rx
+ * timeout occurs).
+ */
+
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+#ifdef CONFIG_USART_ERRINTS
+ ie |= (USART_CR1_RXNEIE|USART_CR1_PEIE|USART_CR3_EIE);
+#else
+ ie |= USART_CR1_RXNEIE;
+#endif
+#endif
+ }
+ else
+ {
+ ie &= ~(USART_CR1_RXNEIE|USART_CR1_PEIE|USART_CR3_EIE);
+ }
+
+ /* Then set the new interrupt state */
+
+ up_restoreusartint(priv, ie);
+ irqrestore(flags);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_rxavailable
+ *
+ * Description:
+ * Return true if the receive register is not empty
+ *
+ ****************************************************************************/
+
+#ifndef SERIAL_HAVE_ONLY_DMA
+static bool up_rxavailable(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ return ((up_serialin(priv, STM32_USART_SR_OFFSET) & USART_SR_RXNE) != 0);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_receive
+ *
+ * Description:
+ * Called (usually) from the interrupt level to receive one
+ * character from the USART. Error bits associated with the
+ * receipt are provided in the return 'status'.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_DMA
+static int up_dma_receive(struct uart_dev_s *dev, uint32_t *status)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ int c = 0;
+
+ if (up_dma_nextrx(priv) != priv->rxdmanext)
+ {
+ c = priv->rxfifo[priv->rxdmanext];
+
+ priv->rxdmanext++;
+ if (priv->rxdmanext == RXDMA_BUFFER_SIZE)
+ {
+ priv->rxdmanext = 0;
+ }
+ }
+
+ return c;
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_rxint
+ *
+ * Description:
+ * Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_DMA
+static void up_dma_rxint(struct uart_dev_s *dev, bool enable)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+
+ /* En/disable DMA reception.
+ *
+ * Note that it is not safe to check for available bytes and immediately
+ * pass them to uart_recvchars as that could potentially recurse back
+ * to us again. Instead, bytes must wait until the next up_dma_poll or
+ * DMA event.
+ */
+
+ priv->rxenable = enable;
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_rxavailable
+ *
+ * Description:
+ * Return true if the receive register is not empty
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_DMA
+static bool up_dma_rxavailable(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+
+ /* Compare our receive pointer to the current DMA pointer, if they
+ * do not match, then there are bytes to be received.
+ */
+
+ return (up_dma_nextrx(priv) != priv->rxdmanext);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_send
+ *
+ * Description:
+ * This method will send one byte on the USART
+ *
+ ****************************************************************************/
+
+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, STM32_USART_DR_OFFSET, (uint32_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;
+ irqstate_t flags;
+
+ /* USART transmit interrupts:
+ *
+ * Enable Bit Status Meaning Usage
+ * ------------------ --- --------------- ---------------------------- ----------
+ * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used)
+ * USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty
+ * USART_CR3_CTSIE 10 USART_SR_CTS CTS flag (not used)
+ */
+
+ flags = irqsave();
+ if (enable)
+ {
+ /* Set to receive an interrupt when the TX data register is empty */
+
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ up_restoreusartint(priv, priv->ie | USART_CR1_TXEIE);
+
+ /* Fake a TX interrupt here by just calling uart_xmitchars() with
+ * interrupts disabled (note this may recurse).
+ */
+
+ uart_xmitchars(dev);
+#endif
+ }
+ else
+ {
+ /* Disable the TX interrupt */
+
+ up_restoreusartint(priv, priv->ie & ~USART_CR1_TXEIE);
+ }
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: up_txready
+ *
+ * Description:
+ * Return true if the tranmsit data register is empty
+ *
+ ****************************************************************************/
+
+static bool up_txready(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ return ((up_serialin(priv, STM32_USART_SR_OFFSET) & USART_SR_TXE) != 0);
+}
+
+/****************************************************************************
+ * Name: up_interrupt_u[s]art[n]
+ *
+ * Description:
+ * Interrupt handlers for U[S]ART[n] where n=1,..,6.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_USART1
+static int up_interrupt_usart1(int irq, void *context)
+{
+ return up_interrupt_common(&g_usart1priv);
+}
+#endif
+
+#ifdef CONFIG_STM32_USART2
+static int up_interrupt_usart2(int irq, void *context)
+{
+ return up_interrupt_common(&g_usart2priv);
+}
+#endif
+
+#ifdef CONFIG_STM32_USART3
+static int up_interrupt_usart3(int irq, void *context)
+{
+ return up_interrupt_common(&g_usart3priv);
+}
+#endif
+
+#ifdef CONFIG_STM32_UART4
+static int up_interrupt_uart4(int irq, void *context)
+{
+ return up_interrupt_common(&g_uart4priv);
+}
+#endif
+
+#ifdef CONFIG_STM32_UART5
+static int up_interrupt_uart5(int irq, void *context)
+{
+ return up_interrupt_common(&g_uart5priv);
+}
+#endif
+
+#ifdef CONFIG_STM32_USART6
+static int up_interrupt_usart6(int irq, void *context)
+{
+ return up_interrupt_common(&g_usart6priv);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_rxcallback
+ *
+ * Description:
+ * This function checks the current DMA state and calls the generic
+ * serial stack when bytes appear to be available.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_DMA
+static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, void *arg)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)arg;
+
+ if (priv->rxenable && up_dma_rxavailable(&priv->dev))
+ {
+ uart_recvchars(&priv->dev);
+ }
+}
+#endif
+
+#endif /* HAVE UART */
+
+/****************************************************************************
+ * Name: up_pm_notify
+ *
+ * Description:
+ * Notify the driver of new power state. This callback is called after
+ * all drivers have had the opportunity to prepare for the new power state.
+ *
+ * Input Parameters:
+ *
+ * cb - Returned to the driver. The driver version of the callback
+ * strucure may include additional, driver-specific state data at
+ * the end of the structure.
+ *
+ * pmstate - Identifies the new PM state
+ *
+ * Returned Value:
+ * None - The driver already agreed to transition to the low power
+ * consumption state when when it returned OK to the prepare() call.
+ *
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static void up_pm_notify(struct pm_callback_s *cb, enum pm_state_e pmstate)
+{
+ switch (pmstate)
+ {
+ case(PM_NORMAL):
+ {
+ /* Logic for PM_NORMAL goes here */
+
+ }
+ break;
+
+ case(PM_IDLE):
+ {
+ /* Logic for PM_IDLE goes here */
+
+ }
+ break;
+
+ case(PM_STANDBY):
+ {
+ /* Logic for PM_STANDBY goes here */
+
+ }
+ break;
+
+ case(PM_SLEEP):
+ {
+ /* Logic for PM_SLEEP goes here */
+
+ }
+ break;
+
+ default:
+ /* Should not get here */
+ break;
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: up_pm_prepare
+ *
+ * Description:
+ * Request the driver to prepare for a new power state. This is a warning
+ * that the system is about to enter into a new power state. The driver
+ * should begin whatever operations that may be required to enter power
+ * state. The driver may abort the state change mode by returning a
+ * non-zero value from the callback function.
+ *
+ * Input Parameters:
+ *
+ * cb - Returned to the driver. The driver version of the callback
+ * strucure may include additional, driver-specific state data at
+ * the end of the structure.
+ *
+ * pmstate - Identifies the new PM state
+ *
+ * Returned Value:
+ * Zero - (OK) means the event was successfully processed and that the
+ * driver is prepared for the PM state change.
+ *
+ * Non-zero - means that the driver is not prepared to perform the tasks
+ * needed achieve this power setting and will cause the state
+ * change to be aborted. NOTE: The prepare() method will also
+ * be called when reverting from lower back to higher power
+ * consumption modes (say because another driver refused a
+ * lower power state change). Drivers are not permitted to
+ * return non-zero values when reverting back to higher power
+ * consumption modes!
+ *
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static int up_pm_prepare(struct pm_callback_s *cb, enum pm_state_e pmstate)
+{
+ /* Logic to prepare for a reduced power state goes here. */
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_earlyserialinit
+ *
+ * Description:
+ * Performs the low level USART 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)
+{
+#ifdef HAVE_UART
+ unsigned i;
+
+ /* Disable all USART interrupts */
+
+ for (i = 0; i < STM32_NUSART; i++)
+ {
+ if (uart_devs[i])
+ {
+ up_disableusartint(uart_devs[i], NULL);
+ }
+ }
+
+ /* Configure whichever one is the console */
+
+#if CONSOLE_UART > 0
+ up_setup(&uart_devs[CONSOLE_UART - 1]->dev);
+#endif
+#endif /* HAVE UART */
+}
+
+/****************************************************************************
+ * Name: up_serialinit
+ *
+ * Description:
+ * Register serial console and serial ports. This assumes
+ * that up_earlyserialinit was called previously.
+ *
+ ****************************************************************************/
+
+void up_serialinit(void)
+{
+#ifdef HAVE_UART
+ char devname[16];
+ unsigned i, j;
+#ifdef CONFIG_PM
+ int ret;
+#endif
+
+ /* Register to receive power management callbacks */
+
+#ifdef CONFIG_PM
+ ret = pm_register(&g_serialcb);
+ DEBUGASSERT(ret == OK);
+#endif
+
+ /* Register the console */
+
+#if CONSOLE_UART > 0
+ (void)uart_register("/dev/console", &uart_devs[CONSOLE_UART - 1]->dev);
+ (void)uart_register("/dev/ttyS0", &uart_devs[CONSOLE_UART - 1]->dev);
+#endif
+
+ /* Register all remaining USARTs */
+
+ strcpy(devname, "/dev/ttySx");
+
+ for (i = 0, j = 1; i < STM32_NUSART; i++)
+ {
+
+ /* don't create a device for the console - we did that above */
+
+ if ((uart_devs[i] == 0) || (uart_devs[i]->dev.isconsole))
+ {
+ continue;
+ }
+
+ /* register USARTs as devices in increasing order */
+
+ devname[9] = '0' + j++;
+ (void)uart_register(devname, &uart_devs[i]->dev);
+ }
+#endif /* HAVE UART */
+}
+
+/****************************************************************************
+ * Name: stm32_serial_dma_poll
+ *
+ * Description:
+ * Checks receive DMA buffers for received bytes that have not accumulated
+ * to the point where the DMA half/full interrupt has triggered.
+ *
+ * This function should be called from a timer or other periodic context.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_DMA
+void stm32_serial_dma_poll(void)
+{
+ irqstate_t flags;
+
+ flags = irqsave();
+
+#ifdef CONFIG_USART1_RXDMA
+ if (g_usart1priv.rxdma != NULL)
+ {
+ up_dma_rxcallback(g_usart1priv.rxdma, 0, &g_usart1priv);
+ }
+#endif
+
+#ifdef CONFIG_USART2_RXDMA
+ if (g_usart2priv.rxdma != NULL)
+ {
+ up_dma_rxcallback(g_usart2priv.rxdma, 0, &g_usart2priv);
+ }
+#endif
+
+#ifdef CONFIG_USART3_RXDMA
+ if (g_usart3priv.rxdma != NULL)
+ {
+ up_dma_rxcallback(g_usart3priv.rxdma, 0, &g_usart3priv);
+ }
+#endif
+
+#ifdef CONFIG_USART4_RXDMA
+ if (g_uart4priv.rxdma != NULL)
+ {
+ up_dma_rxcallback(g_uart4priv.rxdma, 0, &g_uart4priv);
+ }
+#endif
+
+#ifdef CONFIG_USART5_RXDMA
+ if (g_uart5priv.rxdma != NULL)
+ {
+ up_dma_rxcallback(g_uart5priv.rxdma, 0, &g_uart5priv);
+ }
+#endif
+
+#ifdef CONFIG_USART6_RXDMA
+ if (g_usart6priv.rxdma != NULL)
+ {
+ up_dma_rxcallback(g_usart6priv.rxdma, 0, &g_usart6priv);
+ }
+#endif
+
+ irqrestore(flags);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_putc
+ *
+ * Description:
+ * Provide priority, low-level access to support OS debug writes
+ *
+ ****************************************************************************/
+
+int up_putc(int ch)
+{
+#if CONSOLE_UART > 0
+ struct up_dev_s *priv = uart_devs[CONSOLE_UART - 1];
+ uint16_t ie;
+
+ up_disableusartint(priv, &ie);
+
+ /* Check for LF */
+
+ if (ch == '\n')
+ {
+ /* Add CR */
+
+ up_lowputc('\r');
+ }
+
+ up_lowputc(ch);
+ up_restoreusartint(priv, ie);
+#endif
+ return ch;
+}
+
+#else /* USE_SERIALDRIVER */
+
+/****************************************************************************
+ * Name: up_putc
+ *
+ * Description:
+ * Provide priority, low-level access to support OS debug writes
+ *
+ ****************************************************************************/
+
+int up_putc(int ch)
+{
+#if CONSOLE_UART > 0
+ /* Check for LF */
+
+ if (ch == '\n')
+ {
+ /* Add CR */
+
+ up_lowputc('\r');
+ }
+
+ up_lowputc(ch);
+#endif
+ return ch;
+}
+
+#endif /* USE_SERIALDRIVER */
diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.c b/nuttx/arch/arm/src/stm32/stm32_spi.c
new file mode 100644
index 000000000..7fdd988cb
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_spi.c
@@ -0,0 +1,1396 @@
+/************************************************************************************
+ * arm/arm/src/stm32/stm32_spi.c
+ *
+ * Copyright (C) 2009-2012 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.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ * The external functions, stm32_spi1/2/3select and stm32_spi1/2/3status must be
+ * provided by board-specific logic. They are implementations of the select
+ * and status methods of the SPI interface defined by struct spi_ops_s (see
+ * include/nuttx/spi.h). All other methods (including up_spiinitialize())
+ * are provided by common STM32 logic. To use this common SPI logic on your
+ * board:
+ *
+ * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select
+ * pins.
+ * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your
+ * board-specific logic. These functions will perform chip selection and
+ * status operations using GPIOs in the way your board is configured.
+ * 3. Add a calls to up_spiinitialize() in your low level application
+ * initialization logic
+ * 4. The handle returned by up_spiinitialize() may then be used to bind the
+ * SPI driver to higher level logic (e.g., calling
+ * mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ * the SPI MMC/SD driver).
+ *
+ ****************************************************c********************************/
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/spi.h>
+
+#include <arch/board/board.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "chip.h"
+#include "stm32_internal.h"
+#include "stm32_gpio.h"
+#include "stm32_dma.h"
+#include "stm32_spi.h"
+
+#if defined(CONFIG_STM32_SPI1) || defined(CONFIG_STM32_SPI2) || defined(CONFIG_STM32_SPI3)
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+
+#ifdef CONFIG_STM32_SPI_INTERRUPTS
+# error "Interrupt driven SPI not yet supported"
+#endif
+
+#if defined(CONFIG_STM32_SPI_INTERRUPTS) && defined(CONFIG_STM32_SPI_DMA)
+# error "Cannot enable both interrupt mode and DMA mode for SPI"
+#endif
+
+/* DMA channel configuration */
+
+#define SPI_DMA_PRIO DMA_CCR_PRIMED /* Check this to alter priority */
+
+#define SPI_RXDMA16_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC )
+#define SPI_RXDMA8_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC )
+#define SPI_RXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_16BITS )
+#define SPI_RXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS )
+#define SPI_TXDMA16_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC|DMA_CCR_DIR)
+#define SPI_TXDMA8_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC|DMA_CCR_DIR)
+#define SPI_TXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_16BITS |DMA_CCR_DIR)
+#define SPI_TXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_DIR)
+
+/* Debug ****************************************************************************/
+/* Check if (non-standard) SPI debug is enabled */
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_DEBUG_VERBOSE
+# undef CONFIG_DEBUG_SPI
+#endif
+
+#ifdef CONFIG_DEBUG_SPI
+# define spidbg lldbg
+# ifdef CONFIG_DEBUG_VERBOSE
+# define spivdbg lldbg
+# else
+# define spivdbg(x...)
+# endif
+#else
+# define spidbg(x...)
+# define spivdbg(x...)
+#endif
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+
+struct stm32_spidev_s
+{
+ struct spi_dev_s spidev; /* Externally visible part of the SPI interface */
+ uint32_t spibase; /* SPIn base address */
+ uint32_t spiclock; /* Clocking for the SPI module */
+#ifdef CONFIG_STM32_SPI_INTERRUPTS
+ uint8_t spiirq; /* SPI IRQ number */
+#endif
+#ifdef CONFIG_STM32_SPI_DMA
+ volatile uint8_t rxresult; /* Result of the RX DMA */
+ volatile uint8_t txresult; /* Result of the RX DMA */
+ uint8_t rxch; /* The RX DMA channel number */
+ uint8_t txch; /* The TX DMA channel number */
+ DMA_HANDLE rxdma; /* DMA channel handle for RX transfers */
+ DMA_HANDLE txdma; /* DMA channel handle for TX transfers */
+ sem_t rxsem; /* Wait for RX DMA to complete */
+ sem_t txsem; /* Wait for TX DMA to complete */
+#endif
+#ifndef CONFIG_SPI_OWNBUS
+ sem_t exclsem; /* Held while chip is selected for mutual exclusion */
+ uint32_t frequency; /* Requested clock frequency */
+ uint32_t actual; /* Actual clock frequency */
+ uint8_t nbits; /* Width of word in bits (8 or 16) */
+ uint8_t mode; /* Mode 0,1,2,3 */
+#endif
+};
+
+/************************************************************************************
+ * Private Function Prototypes
+ ************************************************************************************/
+
+/* Helpers */
+
+static inline uint16_t spi_getreg(FAR struct stm32_spidev_s *priv, uint8_t offset);
+static inline void spi_putreg(FAR struct stm32_spidev_s *priv, uint8_t offset,
+ uint16_t value);
+static inline uint16_t spi_readword(FAR struct stm32_spidev_s *priv);
+static inline void spi_writeword(FAR struct stm32_spidev_s *priv, uint16_t byte);
+static inline bool spi_16bitmode(FAR struct stm32_spidev_s *priv);
+
+/* DMA support */
+
+#ifdef CONFIG_STM32_SPI_DMA
+static void spi_dmarxwait(FAR struct stm32_spidev_s *priv);
+static void spi_dmatxwait(FAR struct stm32_spidev_s *priv);
+static inline void spi_dmarxwakeup(FAR struct stm32_spidev_s *priv);
+static inline void spi_dmatxwakeup(FAR struct stm32_spidev_s *priv);
+static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr, void *arg);
+static void spi_dmatxcallback(DMA_HANDLE handle, uint8_t isr, void *arg);
+static void spi_dmarxsetup(FAR struct stm32_spidev_s *priv,
+ FAR void *rxbuffer, FAR void *rxdummy, size_t nwords);
+static void spi_dmatxsetup(FAR struct stm32_spidev_s *priv,
+ FAR const void *txbuffer, FAR const void *txdummy, size_t nwords);
+static inline void spi_dmarxstart(FAR struct stm32_spidev_s *priv);
+static inline void spi_dmatxstart(FAR struct stm32_spidev_s *priv);
+#endif
+
+/* SPI methods */
+
+#ifndef CONFIG_SPI_OWNBUS
+static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
+#endif
+static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency);
+static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
+static void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
+static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd);
+static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
+ FAR void *rxbuffer, size_t nwords);
+#ifndef CONFIG_SPI_EXCHANGE
+static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
+ size_t nwords);
+static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer,
+ size_t nwords);
+#endif
+
+/* Initialization */
+
+static void spi_portinitialize(FAR struct stm32_spidev_s *priv);
+
+/************************************************************************************
+ * Private Data
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI1
+static const struct spi_ops_s g_sp1iops =
+{
+#ifndef CONFIG_SPI_OWNBUS
+ .lock = spi_lock,
+#endif
+ .select = stm32_spi1select,
+ .setfrequency = spi_setfrequency,
+ .setmode = spi_setmode,
+ .setbits = spi_setbits,
+ .status = stm32_spi1status,
+#ifdef CONFIG_SPI_CMDDATA
+ .cmddata = stm32_spi1cmddata,
+#endif
+ .send = spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+ .exchange = spi_exchange,
+#else
+ .sndblock = spi_sndblock,
+ .recvblock = spi_recvblock,
+#endif
+ .registercallback = 0,
+};
+
+static struct stm32_spidev_s g_spi1dev =
+{
+ .spidev = { &g_sp1iops },
+ .spibase = STM32_SPI1_BASE,
+ .spiclock = STM32_PCLK2_FREQUENCY,
+#ifdef CONFIG_STM32_SPI_INTERRUPTS
+ .spiirq = STM32_IRQ_SPI1,
+#endif
+#ifdef CONFIG_STM32_SPI_DMA
+ .rxch = DMACHAN_SPI1_RX,
+ .txch = DMACHAN_SPI1_TX,
+#endif
+};
+#endif
+
+#ifdef CONFIG_STM32_SPI2
+static const struct spi_ops_s g_sp2iops =
+{
+#ifndef CONFIG_SPI_OWNBUS
+ .lock = spi_lock,
+#endif
+ .select = stm32_spi2select,
+ .setfrequency = spi_setfrequency,
+ .setmode = spi_setmode,
+ .setbits = spi_setbits,
+ .status = stm32_spi2status,
+#ifdef CONFIG_SPI_CMDDATA
+ .cmddata = stm32_spi2cmddata,
+#endif
+ .send = spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+ .exchange = spi_exchange,
+#else
+ .sndblock = spi_sndblock,
+ .recvblock = spi_recvblock,
+#endif
+ .registercallback = 0,
+};
+
+static struct stm32_spidev_s g_spi2dev =
+{
+ .spidev = { &g_sp2iops },
+ .spibase = STM32_SPI2_BASE,
+ .spiclock = STM32_PCLK1_FREQUENCY,
+#ifdef CONFIG_STM32_SPI_INTERRUPTS
+ .spiirq = STM32_IRQ_SPI2,
+#endif
+#ifdef CONFIG_STM32_SPI_DMA
+ .rxch = DMACHAN_SPI2_RX,
+ .txch = DMACHAN_SPI2_TX,
+#endif
+};
+#endif
+
+#ifdef CONFIG_STM32_SPI3
+static const struct spi_ops_s g_sp3iops =
+{
+#ifndef CONFIG_SPI_OWNBUS
+ .lock = spi_lock,
+#endif
+ .select = stm32_spi3select,
+ .setfrequency = spi_setfrequency,
+ .setmode = spi_setmode,
+ .setbits = spi_setbits,
+ .status = stm32_spi3status,
+#ifdef CONFIG_SPI_CMDDATA
+ .cmddata = stm32_spi3cmddata,
+#endif
+ .send = spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+ .exchange = spi_exchange,
+#else
+ .sndblock = spi_sndblock,
+ .recvblock = spi_recvblock,
+#endif
+ .registercallback = 0,
+};
+
+static struct stm32_spidev_s g_spi3dev =
+{
+ .spidev = { &g_sp3iops },
+ .spibase = STM32_SPI3_BASE,
+ .spiclock = STM32_PCLK1_FREQUENCY,
+#ifdef CONFIG_STM32_SPI_INTERRUPTS
+ .spiirq = STM32_IRQ_SPI3,
+#endif
+#ifdef CONFIG_STM32_SPI_DMA
+ .rxch = DMACHAN_SPI3_RX,
+ .txch = DMACHAN_SPI3_TX,
+#endif
+};
+#endif
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: spi_getreg
+ *
+ * Description:
+ * Get the contents of the SPI register at offset
+ *
+ * Input Parameters:
+ * priv - private SPI device structure
+ * offset - offset to the register of interest
+ *
+ * Returned Value:
+ * The contents of the 16-bit register
+ *
+ ************************************************************************************/
+
+static inline uint16_t spi_getreg(FAR struct stm32_spidev_s *priv, uint8_t offset)
+{
+ return getreg16(priv->spibase + offset);
+}
+
+/************************************************************************************
+ * Name: spi_putreg
+ *
+ * Description:
+ * Write a 16-bit value to the SPI register at offset
+ *
+ * Input Parameters:
+ * priv - private SPI device structure
+ * offset - offset to the register of interest
+ * value - the 16-bit value to be written
+ *
+ * Returned Value:
+ * The contents of the 16-bit register
+ *
+ ************************************************************************************/
+
+static inline void spi_putreg(FAR struct stm32_spidev_s *priv, uint8_t offset, uint16_t value)
+{
+ putreg16(value, priv->spibase + offset);
+}
+
+/************************************************************************************
+ * Name: spi_readword
+ *
+ * Description:
+ * Read one byte from SPI
+ *
+ * Input Parameters:
+ * priv - Device-specific state data
+ *
+ * Returned Value:
+ * Byte as read
+ *
+ ************************************************************************************/
+
+static inline uint16_t spi_readword(FAR struct stm32_spidev_s *priv)
+{
+ /* Wait until the receive buffer is not empty */
+
+ while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_RXNE) == 0);
+
+ /* Then return the received byte */
+
+ return spi_getreg(priv, STM32_SPI_DR_OFFSET);
+}
+
+/************************************************************************************
+ * Name: spi_writeword
+ *
+ * Description:
+ * Write one byte to SPI
+ *
+ * Input Parameters:
+ * priv - Device-specific state data
+ * byte - Byte to send
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static inline void spi_writeword(FAR struct stm32_spidev_s *priv, uint16_t word)
+{
+ /* Wait until the transmit buffer is empty */
+
+ while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_TXE) == 0);
+
+ /* Then send the byte */
+
+ spi_putreg(priv, STM32_SPI_DR_OFFSET, word);
+}
+
+/************************************************************************************
+ * Name: spi_16bitmode
+ *
+ * Description:
+ * Check if the SPI is operating in 16-bit mode
+ *
+ * Input Parameters:
+ * priv - Device-specific state data
+ *
+ * Returned Value:
+ * true: 16-bit mode, false: 8-bit mode
+ *
+ ************************************************************************************/
+
+static inline bool spi_16bitmode(FAR struct stm32_spidev_s *priv)
+{
+ return ((spi_getreg(priv, STM32_SPI_CR1_OFFSET) & SPI_CR1_DFF) != 0);
+}
+
+/************************************************************************************
+ * Name: spi_dmarxwait
+ *
+ * Description:
+ * Wait for DMA to complete.
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static void spi_dmarxwait(FAR struct stm32_spidev_s *priv)
+{
+ /* Take the semaphore (perhaps waiting). If the result is zero, then the DMA
+ * must not really have completed???
+ */
+
+ while (sem_wait(&priv->rxsem) != 0 && priv->rxresult == 0)
+ {
+ /* The only case that an error should occur here is if the wait was awakened
+ * by a signal.
+ */
+
+ ASSERT(errno == EINTR);
+ }
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_dmatxwait
+ *
+ * Description:
+ * Wait for DMA to complete.
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static void spi_dmatxwait(FAR struct stm32_spidev_s *priv)
+{
+ /* Take the semaphore (perhaps waiting). If the result is zero, then the DMA
+ * must not really have completed???
+ */
+
+ while (sem_wait(&priv->txsem) != 0 && priv->txresult == 0)
+ {
+ /* The only case that an error should occur here is if the wait was awakened
+ * by a signal.
+ */
+
+ ASSERT(errno == EINTR);
+ }
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_dmarxwakeup
+ *
+ * Description:
+ * Signal that DMA is complete
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static inline void spi_dmarxwakeup(FAR struct stm32_spidev_s *priv)
+{
+ (void)sem_post(&priv->rxsem);
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_dmarxcallback
+ *
+ * Description:
+ * Called when the RX DMA completes
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr, void *arg)
+{
+ FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)arg;
+
+ /* Wake-up the SPI driver */
+
+ priv->rxresult = isr | 0x080; /* OR'ed with 0x80 to assure non-zero */
+ spi_dmarxwakeup(priv);
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_dmatxcallback
+ *
+ * Description:
+ * Called when the RX DMA completes
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static void spi_dmatxcallback(DMA_HANDLE handle, uint8_t isr, void *arg)
+{
+ FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)arg;
+
+ /* Wake-up the SPI driver */
+
+ priv->txresult = isr | 0x080; /* OR'ed with 0x80 to assure non-zero */
+ spi_dmatxwakeup(priv);
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_dmarxsetup
+ *
+ * Description:
+ * Setup to perform RX DMA
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static void spi_dmarxsetup(FAR struct stm32_spidev_s *priv, FAR void *rxbuffer,
+ FAR void *rxdummy, size_t nwords)
+{
+ uint32_t ccr;
+
+ /* 8- or 16-bit mode? */
+
+ if (spi_16bitmode(priv))
+ {
+ /* 16-bit mode -- is there a buffer to receive data in? */
+
+ if (rxbuffer)
+ {
+ ccr = SPI_RXDMA16_CONFIG;
+ }
+ else
+ {
+ rxbuffer = rxdummy;
+ ccr = SPI_RXDMA16NULL_CONFIG;
+ }
+ }
+ else
+ {
+ /* 8-bit mode -- is there a buffer to receive data in? */
+
+ if (rxbuffer)
+ {
+ ccr = SPI_RXDMA8_CONFIG;
+ }
+ else
+ {
+ rxbuffer = rxdummy;
+ ccr = SPI_RXDMA8NULL_CONFIG;
+ }
+ }
+
+ /* Configure the RX DMA */
+
+ stm32_dmasetup(priv->rxdma, priv->spibase + STM32_SPI_DR_OFFSET, (uint32_t)rxbuffer, nwords, ccr);
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_dmatxsetup
+ *
+ * Description:
+ * Setup to perform TX DMA
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static void spi_dmatxsetup(FAR struct stm32_spidev_s *priv, FAR const void *txbuffer,
+ FAR const void *txdummy, size_t nwords)
+{
+ uint32_t ccr;
+
+ /* 8- or 16-bit mode? */
+
+ if (spi_16bitmode(priv))
+ {
+ /* 16-bit mode -- is there a buffer to transfer data from? */
+
+ if (txbuffer)
+ {
+ ccr = SPI_TXDMA16_CONFIG;
+ }
+ else
+ {
+ txbuffer = txdummy;
+ ccr = SPI_TXDMA16NULL_CONFIG;
+ }
+ }
+ else
+ {
+ /* 8-bit mode -- is there a buffer to transfer data from? */
+
+ if (txbuffer)
+ {
+ ccr = SPI_TXDMA8_CONFIG;
+ }
+ else
+ {
+ txbuffer = txdummy;
+ ccr = SPI_TXDMA8NULL_CONFIG;
+ }
+ }
+
+ /* Setup the TX DMA */
+
+ stm32_dmasetup(priv->txdma, priv->spibase + STM32_SPI_DR_OFFSET,(uint32_t)txbuffer, nwords, ccr);
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_dmarxstart
+ *
+ * Description:
+ * Start RX DMA
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static inline void spi_dmarxstart(FAR struct stm32_spidev_s *priv)
+{
+ stm32_dmastart(priv->rxdma, spi_dmarxcallback, priv, false);
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_dmatxstart
+ *
+ * Description:
+ * Start TX DMA
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static inline void spi_dmatxstart(FAR struct stm32_spidev_s *priv)
+{
+ stm32_dmastart(priv->txdma, spi_dmatxcallback, priv, false);
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_modifycr1
+ *
+ * Description:
+ * Clear and set bits in the CR1 register
+ *
+ * Input Parameters:
+ * priv - Device-specific state data
+ * clrbits - The bits to clear
+ * setbits - The bits to set
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static void spi_modifycr1(FAR struct stm32_spidev_s *priv, uint16_t setbits, uint16_t clrbits)
+{
+ uint16_t cr1;
+ cr1 = spi_getreg(priv, STM32_SPI_CR1_OFFSET);
+ cr1 &= ~clrbits;
+ cr1 |= setbits;
+ spi_putreg(priv, STM32_SPI_CR1_OFFSET, cr1);
+}
+
+/****************************************************************************
+ * Name: spi_lock
+ *
+ * Description:
+ * On SPI busses where there are multiple devices, it will be necessary to
+ * lock SPI to have exclusive access to the busses for a sequence of
+ * transfers. The bus should be locked before the chip is selected. After
+ * locking the SPI bus, the caller should then also call the setfrequency,
+ * setbits, and setmode methods to make sure that the SPI is properly
+ * configured for the device. If the SPI buss is being shared, then it
+ * may have been left in an incompatible state.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * lock - true: Lock spi bus, false: unlock SPI bus
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_SPI_OWNBUS
+static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
+{
+ FAR struct stm32_spidev_s *priv = (FAR struct stm32_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.
+ */
+
+ ASSERT(errno == EINTR);
+ }
+ }
+ else
+ {
+ (void)sem_post(&priv->exclsem);
+ }
+ return OK;
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_setfrequency
+ *
+ * Description:
+ * Set the SPI frequency.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * frequency - The SPI frequency requested
+ *
+ * Returned Value:
+ * Returns the actual frequency selected
+ *
+ ************************************************************************************/
+
+static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
+{
+ FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
+ uint16_t setbits;
+ uint32_t actual;
+
+ /* Limit to max possible (if STM32_SPI_CLK_MAX is defined in board.h) */
+
+ if (frequency > STM32_SPI_CLK_MAX)
+ {
+ frequency = STM32_SPI_CLK_MAX;
+ }
+
+ /* Has the frequency changed? */
+
+#ifndef CONFIG_SPI_OWNBUS
+ if (frequency != priv->frequency)
+ {
+#endif
+ /* Choices are limited by PCLK frequency with a set of divisors */
+
+ if (frequency >= priv->spiclock >> 1)
+ {
+ /* More than fPCLK/2. This is as fast as we can go */
+
+ setbits = SPI_CR1_FPCLCKd2; /* 000: fPCLK/2 */
+ actual = priv->spiclock >> 1;
+ }
+ else if (frequency >= priv->spiclock >> 2)
+ {
+ /* Between fPCLCK/2 and fPCLCK/4, pick the slower */
+
+ setbits = SPI_CR1_FPCLCKd4; /* 001: fPCLK/4 */
+ actual = priv->spiclock >> 2;
+ }
+ else if (frequency >= priv->spiclock >> 3)
+ {
+ /* Between fPCLCK/4 and fPCLCK/8, pick the slower */
+
+ setbits = SPI_CR1_FPCLCKd8; /* 010: fPCLK/8 */
+ actual = priv->spiclock >> 3;
+ }
+ else if (frequency >= priv->spiclock >> 4)
+ {
+ /* Between fPCLCK/8 and fPCLCK/16, pick the slower */
+
+ setbits = SPI_CR1_FPCLCKd16; /* 011: fPCLK/16 */
+ actual = priv->spiclock >> 4;
+ }
+ else if (frequency >= priv->spiclock >> 5)
+ {
+ /* Between fPCLCK/16 and fPCLCK/32, pick the slower */
+
+ setbits = SPI_CR1_FPCLCKd32; /* 100: fPCLK/32 */
+ actual = priv->spiclock >> 5;
+ }
+ else if (frequency >= priv->spiclock >> 6)
+ {
+ /* Between fPCLCK/32 and fPCLCK/64, pick the slower */
+
+ setbits = SPI_CR1_FPCLCKd64; /* 101: fPCLK/64 */
+ actual = priv->spiclock >> 6;
+ }
+ else if (frequency >= priv->spiclock >> 7)
+ {
+ /* Between fPCLCK/64 and fPCLCK/128, pick the slower */
+
+ setbits = SPI_CR1_FPCLCKd128; /* 110: fPCLK/128 */
+ actual = priv->spiclock >> 7;
+ }
+ else
+ {
+ /* Less than fPCLK/128. This is as slow as we can go */
+
+ setbits = SPI_CR1_FPCLCKd256; /* 111: fPCLK/256 */
+ actual = priv->spiclock >> 8;
+ }
+
+ spi_modifycr1(priv, setbits, SPI_CR1_BR_MASK);
+
+ /* Save the frequency selection so that subsequent reconfigurations will be
+ * faster.
+ */
+
+ spivdbg("Frequency %d->%d\n", frequency, actual);
+
+#ifndef CONFIG_SPI_OWNBUS
+ priv->frequency = frequency;
+ priv->actual = actual;
+ }
+ return priv->actual;
+#else
+ return actual;
+#endif
+}
+
+/************************************************************************************
+ * Name: spi_setmode
+ *
+ * Description:
+ * Set the SPI mode. see enum spi_mode_e for mode definitions
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * mode - The SPI mode requested
+ *
+ * Returned Value:
+ * Returns the actual frequency selected
+ *
+ ************************************************************************************/
+
+static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
+{
+ FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
+ uint16_t setbits;
+ uint16_t clrbits;
+
+ spivdbg("mode=%d\n", mode);
+
+ /* Has the mode changed? */
+
+#ifndef CONFIG_SPI_OWNBUS
+ if (mode != priv->mode)
+ {
+#endif
+ /* Yes... Set CR1 appropriately */
+
+ switch (mode)
+ {
+ case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */
+ setbits = 0;
+ clrbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
+ break;
+
+ case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
+ setbits = SPI_CR1_CPHA;
+ clrbits = SPI_CR1_CPOL;
+ break;
+
+ case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
+ setbits = SPI_CR1_CPOL;
+ clrbits = SPI_CR1_CPHA;
+ break;
+
+ case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
+ setbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
+ clrbits = 0;
+ break;
+
+ default:
+ return;
+ }
+
+ spi_modifycr1(priv, setbits, clrbits);
+
+ /* Save the mode so that subsequent re-configurations will be faster */
+
+#ifndef CONFIG_SPI_OWNBUS
+ priv->mode = mode;
+ }
+#endif
+}
+
+/************************************************************************************
+ * Name: spi_setbits
+ *
+ * Description:
+ * Set the number of bits per word.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * nbits - The number of bits requested
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
+{
+ FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
+ uint16_t setbits;
+ uint16_t clrbits;
+
+ spivdbg("nbits=%d\n", nbits);
+
+ /* Has the number of bits changed? */
+
+#ifndef CONFIG_SPI_OWNBUS
+ if (nbits != priv->nbits)
+ {
+#endif
+ /* Yes... Set CR1 appropriately */
+
+ switch (nbits)
+ {
+ case 8:
+ setbits = 0;
+ clrbits = SPI_CR1_DFF;
+ break;
+
+ case 16:
+ setbits = SPI_CR1_DFF;
+ clrbits = 0;
+ break;
+
+ default:
+ return;
+ }
+
+ spi_modifycr1(priv, setbits, clrbits);
+
+ /* Save the selection so the subsequence re-configurations will be faster */
+
+#ifndef CONFIG_SPI_OWNBUS
+ priv->nbits = nbits;
+ }
+#endif
+}
+
+/************************************************************************************
+ * Name: spi_send
+ *
+ * Description:
+ * Exchange one word on SPI
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * wd - The word to send. the size of the data is determined by the
+ * number of bits selected for the SPI interface.
+ *
+ * Returned Value:
+ * response
+ *
+ ************************************************************************************/
+
+static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
+{
+ FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
+ uint16_t ret;
+
+ DEBUGASSERT(priv && priv->spibase);
+
+ spi_writeword(priv, wd);
+ ret = spi_readword(priv);
+
+ spivdbg("Sent: %04x Return: %04x\n", wd, ret);
+ return ret;
+}
+
+/*************************************************************************
+ * Name: spi_exchange (no DMA)
+ *
+ * Description:
+ * Exchange a block of data on SPI without using DMA
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * txbuffer - A pointer to the buffer of data to be sent
+ * rxbuffer - A pointer to a buffer in which to receive data
+ * nwords - the length of data to be exchaned in units of words.
+ * The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifndef CONFIG_STM32_SPI_DMA
+static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
+ FAR void *rxbuffer, size_t nwords)
+{
+ FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
+ DEBUGASSERT(priv && priv->spibase);
+
+ spivdbg("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords);
+
+ /* 8- or 16-bit mode? */
+
+ if (spi_16bitmode(priv))
+ {
+ /* 16-bit mode */
+
+ const uint16_t *src = (const uint16_t*)txbuffer;;
+ uint16_t *dest = (uint16_t*)rxbuffer;
+ uint16_t word;
+
+ while (nwords-- > 0)
+ {
+ /* Get the next word to write. Is there a source buffer? */
+
+ if (src)
+ {
+ word = *src++;
+ }
+ else
+ {
+ word = 0xffff;
+ }
+
+ /* Exchange one word */
+
+ word = spi_send(dev, word);
+
+ /* Is there a buffer to receive the return value? */
+
+ if (dest)
+ {
+ *dest++ = word;
+ }
+ }
+ }
+ else
+ {
+ /* 8-bit mode */
+
+ const uint8_t *src = (const uint8_t*)txbuffer;;
+ uint8_t *dest = (uint8_t*)rxbuffer;
+ uint8_t word;
+
+ while (nwords-- > 0)
+ {
+ /* Get the next word to write. Is there a source buffer? */
+
+ if (src)
+ {
+ word = *src++;
+ }
+ else
+ {
+ word = 0xff;
+ }
+
+ /* Exchange one word */
+
+ word = (uint8_t)spi_send(dev, (uint16_t)word);
+
+ /* Is there a buffer to receive the return value? */
+
+ if (dest)
+ {
+ *dest++ = word;
+ }
+ }
+ }
+}
+#endif
+
+/*************************************************************************
+ * Name: spi_exchange (with DMA capability)
+ *
+ * Description:
+ * Exchange a block of data on SPI using DMA
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * txbuffer - A pointer to the buffer of data to be sent
+ * rxbuffer - A pointer to a buffer in which to receive data
+ * nwords - the length of data to be exchanged in units of words.
+ * The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
+ FAR void *rxbuffer, size_t nwords)
+{
+ FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
+ uint16_t rxdummy = 0xffff;
+ uint16_t txdummy;
+
+ spivdbg("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords);
+ DEBUGASSERT(priv && priv->spibase);
+
+ /* Setup DMAs */
+
+ spi_dmarxsetup(priv, rxbuffer, &rxdummy, nwords);
+ spi_dmatxsetup(priv, txbuffer, &txdummy, nwords);
+
+ /* Start the DMAs */
+
+ spi_dmarxstart(priv);
+ spi_dmatxstart(priv);
+
+ /* Then wait for each to complete */
+
+ spi_dmarxwait(priv);
+ spi_dmatxwait(priv);
+}
+#endif
+
+/*************************************************************************
+ * Name: spi_sndblock
+ *
+ * Description:
+ * Send a block of data on SPI
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * txbuffer - A pointer to the buffer of data to be sent
+ * nwords - the length of data to send from the buffer in number of words.
+ * The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifndef CONFIG_SPI_EXCHANGE
+static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer, size_t nwords)
+{
+ spivdbg("txbuffer=%p nwords=%d\n", txbuffer, nwords);
+ return spi_exchange(dev, txbuffer, NULL, nwords);
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_recvblock
+ *
+ * Description:
+ * Receive a block of data from SPI
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * rxbuffer - A pointer to the buffer in which to recieve data
+ * nwords - the length of data that can be received in the buffer in number
+ * of words. The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifndef CONFIG_SPI_EXCHANGE
+static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer, size_t nwords)
+{
+ spivdbg("rxbuffer=%p nwords=%d\n", rxbuffer, nwords);
+ return spi_exchange(dev, NULL, rxbuffer, nwords);
+}
+#endif
+
+/************************************************************************************
+ * Name: spi_portinitialize
+ *
+ * Description:
+ * Initialize the selected SPI port in its default state (Master, 8-bit, mode 0, etc.)
+ *
+ * Input Parameter:
+ * priv - private SPI device structure
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static void spi_portinitialize(FAR struct stm32_spidev_s *priv)
+{
+ uint16_t setbits;
+ uint16_t clrbits;
+
+ /* Configure CR1. Default configuration:
+ * Mode 0: CPHA=0 and CPOL=0
+ * Master: MSTR=1
+ * 8-bit: DFF=0
+ * MSB tranmitted first: LSBFIRST=0
+ * Replace NSS with SSI & SSI=1: SSI=1 SSM=1 (prevents MODF error)
+ * Two lines full duplex: BIDIMODE=0 BIDIOIE=(Don't care) and RXONLY=0
+ */
+
+ clrbits = SPI_CR1_CPHA|SPI_CR1_CPOL|SPI_CR1_BR_MASK|SPI_CR1_LSBFIRST|
+ SPI_CR1_RXONLY|SPI_CR1_DFF|SPI_CR1_BIDIOE|SPI_CR1_BIDIMODE;
+ setbits = SPI_CR1_MSTR|SPI_CR1_SSI|SPI_CR1_SSM;
+ spi_modifycr1(priv, setbits, clrbits);
+
+#ifndef CONFIG_SPI_OWNBUS
+ priv->frequency = 0;
+ priv->nbits = 8;
+ priv->mode = SPIDEV_MODE0;
+#endif
+
+ /* Select a default frequency of approx. 400KHz */
+
+ spi_setfrequency((FAR struct spi_dev_s *)priv, 400000);
+
+ /* CRCPOLY configuration */
+
+ spi_putreg(priv, STM32_SPI_CRCPR_OFFSET, 7);
+
+ /* Initialize the SPI semaphore that enforces mutually exclusive access */
+
+#ifndef CONFIG_SPI_OWNBUS
+ sem_init(&priv->exclsem, 0, 1);
+#endif
+
+ /* Initialize the SPI semaphores that is used to wait for DMA completion */
+
+#ifdef CONFIG_STM32_SPI_DMA
+ sem_init(&priv->rxsem, 0, 0);
+ sem_init(&priv->txsem, 0, 0);
+
+ /* Get DMA channels. NOTE: stm32_dmachannel() will always assign the DMA channel.
+ * if the channel is not available, then stm32_dmachannel() will block and wait
+ * until the channel becomes available. WARNING: If you have another device sharing
+ * a DMA channel with SPI and the code never releases that channel, then the call
+ * to stm32_dmachannel() will hang forever in this function! Don't let your
+ * design do that!
+ */
+
+ priv->rxdma = stm32_dmachannel(priv->rxch);
+ priv->txdma = stm32_dmachannel(priv->txch);
+ DEBUGASSERT(priv->rxdma && priv->txdma);
+#endif
+
+ /* Enable spi */
+
+ spi_modifycr1(priv, SPI_CR1_SPE, 0);
+}
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_spiinitialize
+ *
+ * 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 *up_spiinitialize(int port)
+{
+ FAR struct stm32_spidev_s *priv = NULL;
+
+ irqstate_t flags = irqsave();
+
+#ifdef CONFIG_STM32_SPI1
+ if (port == 1)
+ {
+ /* Select SPI1 */
+
+ priv = &g_spi1dev;
+
+ /* Configure SPI1 pins: SCK, MISO, and MOSI */
+
+ stm32_configgpio(GPIO_SPI1_SCK);
+ stm32_configgpio(GPIO_SPI1_MISO);
+ stm32_configgpio(GPIO_SPI1_MOSI);
+
+ /* Set up default configuration: Master, 8-bit, etc. */
+
+ spi_portinitialize(priv);
+ }
+ else
+#endif
+#ifdef CONFIG_STM32_SPI2
+ if (port == 2)
+ {
+ /* Select SPI2 */
+
+ priv = &g_spi2dev;
+
+ /* Configure SPI2 pins: SCK, MISO, and MOSI */
+
+ stm32_configgpio(GPIO_SPI2_SCK);
+ stm32_configgpio(GPIO_SPI2_MISO);
+ stm32_configgpio(GPIO_SPI2_MOSI);
+
+ /* Set up default configuration: Master, 8-bit, etc. */
+
+ spi_portinitialize(priv);
+ }
+ else
+#endif
+#ifdef CONFIG_STM32_SPI3
+ if (port == 3)
+ {
+ /* Select SPI3 */
+
+ priv = &g_spi3dev;
+
+ /* Configure SPI3 pins: SCK, MISO, and MOSI */
+
+ stm32_configgpio(GPIO_SPI3_SCK);
+ stm32_configgpio(GPIO_SPI3_MISO);
+ stm32_configgpio(GPIO_SPI3_MOSI);
+
+ /* Set up default configuration: Master, 8-bit, etc. */
+
+ spi_portinitialize(priv);
+ }
+#endif
+
+ irqrestore(flags);
+ return (FAR struct spi_dev_s *)priv;
+}
+
+#endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 || CONFIG_STM32_SPI3 */
diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.h b/nuttx/arch/arm/src/stm32/stm32_spi.h
new file mode 100644
index 000000000..268589bf3
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_spi.h
@@ -0,0 +1,121 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_spi.h
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STC_STM32_STM32_SPI_H
+#define __ARCH_ARM_STC_STM32_STM32_SPI_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_spi.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+struct spi_dev_s;
+enum spi_dev_e;
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_spi1/2/3select and stm32_spi1/2/3status
+ *
+ * Description:
+ * The external functions, stm32_spi1/2/3select, stm32_spi1/2/3status, and
+ * stm32_spi1/2/3cmddata must be provided by board-specific logic. These are
+ * implementations of the select, status, and cmddata methods of the SPI interface
+ * defined by struct spi_ops_s (see include/nuttx/spi.h). All other methods
+ * (including up_spiinitialize()) are provided by common STM32 logic. To use this
+ * common SPI logic on your board:
+ *
+ * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select
+ * pins.
+ * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your
+ * board-specific logic. These functions will perform chip selection and
+ * status operations using GPIOs in the way your board is configured.
+ * 3. If CONFIG_SPI_CMDDATA is defined in your NuttX configuration file, then
+ * provide stm32_spi1/2/3cmddata() functions in your board-specific logic.
+ * These functions will perform cmd/data selection operations using GPIOs in the
+ * way your board is configured.
+ * 4. Add a calls to up_spiinitialize() in your low level application
+ * initialization logic
+ * 5. The handle returned by up_spiinitialize() may then be used to bind the
+ * SPI driver to higher level logic (e.g., calling
+ * mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ * the SPI MMC/SD driver).
+ *
+ ************************************************************************************/
+
+EXTERN void stm32_spi1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
+EXTERN uint8_t stm32_spi1status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
+EXTERN int stm32_spi1cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
+
+EXTERN void stm32_spi2select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
+EXTERN uint8_t stm32_spi2status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
+EXTERN int stm32_spi2cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
+
+EXTERN void stm32_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
+EXTERN uint8_t stm32_spi3status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
+EXTERN int stm32_spi3cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_STC_STM32_STM32_SPI_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_start.c b/nuttx/arch/arm/src/stm32/stm32_start.c
new file mode 100644
index 000000000..d341121f1
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_start.c
@@ -0,0 +1,240 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_start.c
+ * arch/arm/src/chip/stm32_start.c
+ *
+ * Copyright (C) 2009, 2011-2012 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.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/init.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+
+#include "stm32_internal.h"
+#include "stm32_gpio.h"
+
+#ifdef CONFIG_ARCH_FPU
+# include "nvic.h"
+#endif
+
+/****************************************************************************
+ * Name: showprogress
+ *
+ * Description:
+ * Print a character on the UART to show boot status.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG
+# define showprogress(c) up_lowputc(c)
+#else
+# define showprogress(c)
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* we need to get r10 set before we can allow instrumentation calls */
+
+void __start(void) __attribute__ ((no_instrument_function));
+
+/****************************************************************************
+ * Name: stm32_fpuconfig
+ *
+ * Description:
+ * Configure the FPU. Relative bit settings:
+ *
+ * CPACR: Enables access to CP10 and CP11
+ * CONTROL.FPCA: Determines whether the FP extension is active in the
+ * current context:
+ * FPCCR.ASPEN: Enables automatic FP state preservation, then the
+ * processor sets this bit to 1 on successful completion of any FP
+ * instruction.
+ * FPCCR.LSPEN: Enables lazy context save of FP state. When this is
+ * done, the processor reserves space on the stack for the FP state,
+ * but does not save that state information to the stack.
+ *
+ * Software must not change the value of the ASPEN bit or LSPEN bit while either:
+ * - the CPACR permits access to CP10 and CP11, that give access to the FP
+ * extension, or
+ * - the CONTROL.FPCA bit is set to 1
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_FPU
+#ifdef CONFIG_ARMV7M_CMNVECTOR
+
+static inline void stm32_fpuconfig(void)
+{
+ uint32_t regval;
+
+ /* Set CONTROL.FPCA so that we always get the extended context frame
+ * with the volatile FP registers stacked above the basic context.
+ */
+
+ regval = getcontrol();
+ regval |= (1 << 2);
+ setcontrol(regval);
+
+ /* Ensure that FPCCR.LSPEN is disabled, so that we don't have to contend
+ * with the lazy FP context save behaviour. Clear FPCCR.ASPEN since we
+ * are going to turn on CONTROL.FPCA for all contexts.
+ */
+
+ regval = getreg32(NVIC_FPCCR);
+ regval &= ~((1 << 31) | (1 << 30));
+ putreg32(regval, NVIC_FPCCR);
+
+ /* Enable full access to CP10 and CP11 */
+
+ regval = getreg32(NVIC_CPACR);
+ regval |= ((3 << (2*10)) | (3 << (2*11)));
+ putreg32(regval, NVIC_CPACR);
+}
+
+#else
+
+static inline void stm32_fpuconfig(void)
+{
+ uint32_t regval;
+
+ /* Clear CONTROL.FPCA so that we do not get the extended context frame
+ * with the volatile FP registers stacked in the saved context.
+ */
+
+ regval = getcontrol();
+ regval &= ~(1 << 2);
+ setcontrol(regval);
+
+ /* Ensure that FPCCR.LSPEN is disabled, so that we don't have to contend
+ * with the lazy FP context save behaviour. Clear FPCCR.ASPEN since we
+ * are going to keep CONTROL.FPCA off for all contexts.
+ */
+
+ regval = getreg32(NVIC_FPCCR);
+ regval &= ~((1 << 31) | (1 << 30));
+ putreg32(regval, NVIC_FPCCR);
+
+ /* Enable full access to CP10 and CP11 */
+
+ regval = getreg32(NVIC_CPACR);
+ regval |= ((3 << (2*10)) | (3 << (2*11)));
+ putreg32(regval, NVIC_CPACR);
+}
+
+#endif
+
+#else
+# define stm32_fpuconfig()
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: _start
+ *
+ * Description:
+ * This is the reset entry point.
+ *
+ ****************************************************************************/
+
+void __start(void)
+{
+ const uint32_t *src;
+ uint32_t *dest;
+
+ /* Set the stack limit before we attempt to call any functions */
+
+ __asm__ volatile ("sub r10, sp, %0" : : "r" (CONFIG_IDLETHREAD_STACKSIZE - 64) : );
+
+ /* Configure the uart so that we can get debug output as soon as possible */
+
+ stm32_clockconfig();
+ stm32_fpuconfig();
+ stm32_lowsetup();
+ stm32_gpioinit();
+ showprogress('A');
+
+ /* Clear .bss. We'll do this inline (vs. calling memset) just to be
+ * certain that there are no issues with the state of global variables.
+ */
+
+ for (dest = &_sbss; dest < &_ebss; )
+ {
+ *dest++ = 0;
+ }
+ showprogress('B');
+
+ /* Move the intialized data section from his temporary holding spot in
+ * FLASH into the correct place in SRAM. The correct place in SRAM is
+ * give by _sdata and _edata. The temporary location is in FLASH at the
+ * end of all of the other read-only data (.text, .rodata) at _eronly.
+ */
+
+ for (src = &_eronly, dest = &_sdata; dest < &_edata; )
+ {
+ *dest++ = *src++;
+ }
+ showprogress('C');
+
+ /* Perform early serial initialization */
+
+#ifdef USE_EARLYSERIALINIT
+ up_earlyserialinit();
+#endif
+ showprogress('D');
+
+ /* Initialize onboard resources */
+
+ stm32_boardinitialize();
+ showprogress('E');
+
+ /* Then start NuttX */
+
+ showprogress('\r');
+ showprogress('\n');
+ os_start();
+
+ /* Shoulnd't get here */
+
+ for(;;);
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_syscfg.h b/nuttx/arch/arm/src/stm32/stm32_syscfg.h
new file mode 100644
index 000000000..8a57a2c58
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_syscfg.h
@@ -0,0 +1,104 @@
+/****************************************************************************************************
+ * arch/arm/src/stm32/stm32_syscfg.h
+ *
+ * Copyright (C) 2011 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_STM32_STM32_SYSCFG_H
+#define __ARCH_ARM_SRC_STM32_STM32_SYSCFG_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# include "chip/stm32_syscfg.h"
+
+/****************************************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Inline Functions
+ ****************************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_selectmii
+ *
+ * Description:
+ * Selects the MII inteface.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static inline void stm32_selectmii(void)
+{
+ uint32_t regval;
+
+ regval = getreg32(STM32_SYSCFG_PMC);
+ regval &= ~SYSCFG_PMC_MII_RMII_SEL;
+ putreg32(regval, STM32_SYSCFG_PMC);
+}
+
+/************************************************************************************
+ * Name: stm32_selectrmii
+ *
+ * Description:
+ * Selects the RMII inteface.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static inline void stm32_selectrmii(void)
+{
+ uint32_t regval;
+
+ regval = getreg32(STM32_SYSCFG_PMC);
+ regval |= SYSCFG_PMC_MII_RMII_SEL;
+ putreg32(regval, STM32_SYSCFG_PMC);
+}
+
+#endif /* CONFIG_STM32_STM32F20XX || CONFIG_STM32_STM32F40XX */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_SYSCFG_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_tim.c b/nuttx/arch/arm/src/stm32/stm32_tim.c
new file mode 100644
index 000000000..d19c69c03
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_tim.c
@@ -0,0 +1,1020 @@
+/************************************************************************************
+ * arm/arm/src/stm32/stm32_tim.c
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With modifications and updates by:
+ *
+ * Copyright (C) 2011-2012 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 <nuttx/arch.h>
+#include <nuttx/irq.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "stm32_internal.h"
+#include "stm32_gpio.h"
+#include "stm32_tim.h"
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* Timer devices may be used for different purposes. Such special purposes include:
+ *
+ * - To generate modulated outputs for such things as motor control. If CONFIG_STM32_TIMn
+ * is defined then the CONFIG_STM32_TIMn_PWM may also be defined to indicate that
+ * the timer is intended to be used for pulsed output modulation.
+ *
+ * - To control periodic ADC input sampling. If CONFIG_STM32_TIMn is defined then
+ * CONFIG_STM32_TIMn_ADC may also be defined to indicate that timer "n" is intended
+ * to be used for that purpose.
+ *
+ * - To control periodic DAC outputs. If CONFIG_STM32_TIMn is defined then
+ * CONFIG_STM32_TIMn_DAC may also be defined to indicate that timer "n" is intended
+ * to be used for that purpose.
+ *
+ * - To use a Quadrature Encoder. If CONFIG_STM32_TIMn is defined then
+ * CONFIG_STM32_TIMn_QE may also be defined to indicate that timer "n" is intended
+ * to be used for that purpose.
+ *
+ * In any of these cases, the timer will not be used by this timer module.
+ */
+
+#if defined(CONFIG_STM32_TIM1_PWM) || defined (CONFIG_STM32_TIM1_ADC) || \
+ defined(CONFIG_STM32_TIM1_DAC) || defined(CONFIG_STM32_TIM1_QE)
+# undef CONFIG_STM32_TIM1
+#endif
+#if defined(CONFIG_STM32_TIM2_PWM) || defined (CONFIG_STM32_TIM2_ADC) || \
+ defined(CONFIG_STM32_TIM2_DAC) || defined(CONFIG_STM32_TIM2_QE)
+# undef CONFIG_STM32_TIM2
+#endif
+#if defined(CONFIG_STM32_TIM3_PWM) || defined (CONFIG_STM32_TIM3_ADC) || \
+ defined(CONFIG_STM32_TIM3_DAC) || defined(CONFIG_STM32_TIM3_QE)
+# undef CONFIG_STM32_TIM3
+#endif
+#if defined(CONFIG_STM32_TIM4_PWM) || defined (CONFIG_STM32_TIM4_ADC) || \
+ defined(CONFIG_STM32_TIM4_DAC) || defined(CONFIG_STM32_TIM4_QE)
+# undef CONFIG_STM32_TIM4
+#endif
+#if defined(CONFIG_STM32_TIM5_PWM) || defined (CONFIG_STM32_TIM5_ADC) || \
+ defined(CONFIG_STM32_TIM5_DAC) || defined(CONFIG_STM32_TIM5_QE)
+# undef CONFIG_STM32_TIM5
+#endif
+#if defined(CONFIG_STM32_TIM6_PWM) || defined (CONFIG_STM32_TIM6_ADC) || \
+ defined(CONFIG_STM32_TIM6_DAC) || defined(CONFIG_STM32_TIM6_QE)
+# undef CONFIG_STM32_TIM6
+#endif
+#if defined(CONFIG_STM32_TIM7_PWM) || defined (CONFIG_STM32_TIM7_ADC) || \
+ defined(CONFIG_STM32_TIM7_DAC) || defined(CONFIG_STM32_TIM7_QE)
+# undef CONFIG_STM32_TIM7
+#endif
+#if defined(CONFIG_STM32_TIM8_PWM) || defined (CONFIG_STM32_TIM8_ADC) || \
+ defined(CONFIG_STM32_TIM8_DAC) || defined(CONFIG_STM32_TIM8_QE)
+# undef CONFIG_STM32_TIM8
+#endif
+#if defined(CONFIG_STM32_TIM9_PWM) || defined (CONFIG_STM32_TIM9_ADC) || \
+ defined(CONFIG_STM32_TIM9_DAC) || defined(CONFIG_STM32_TIM9_QE)
+# undef CONFIG_STM32_TIM9
+#endif
+#if defined(CONFIG_STM32_TIM10_PWM) || defined (CONFIG_STM32_TIM10_ADC) || \
+ defined(CONFIG_STM32_TIM10_DAC) || defined(CONFIG_STM32_TIM10_QE)
+# undef CONFIG_STM32_TIM10
+#endif
+#if defined(CONFIG_STM32_TIM11_PWM) || defined (CONFIG_STM32_TIM11_ADC) || \
+ defined(CONFIG_STM32_TIM11_DAC) || defined(CONFIG_STM32_TIM11_QE)
+# undef CONFIG_STM32_TIM11
+#endif
+#if defined(CONFIG_STM32_TIM12_PWM) || defined (CONFIG_STM32_TIM12_ADC) || \
+ defined(CONFIG_STM32_TIM12_DAC) || defined(CONFIG_STM32_TIM12_QE)
+# undef CONFIG_STM32_TIM12
+#endif
+#if defined(CONFIG_STM32_TIM13_PWM) || defined (CONFIG_STM32_TIM13_ADC) || \
+ defined(CONFIG_STM32_TIM13_DAC) || defined(CONFIG_STM32_TIM13_QE)
+# undef CONFIG_STM32_TIM13
+#endif
+#if defined(CONFIG_STM32_TIM14_PWM) || defined (CONFIG_STM32_TIM14_ADC) || \
+ defined(CONFIG_STM32_TIM14_DAC) || defined(CONFIG_STM32_TIM14_QE)
+# undef CONFIG_STM32_TIM14
+#endif
+
+/* This module then only compiles if there are enabled timers that are not intended for
+ * some other purpose.
+ */
+
+#if defined(CONFIG_STM32_TIM1) || defined(CONFIG_STM32_TIM2) || defined(CONFIG_STM32_TIM3) || \
+ defined(CONFIG_STM32_TIM4) || defined(CONFIG_STM32_TIM5) || defined(CONFIG_STM32_TIM6) || \
+ defined(CONFIG_STM32_TIM7) || defined(CONFIG_STM32_TIM8)
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+
+/* TIM Device Structure */
+
+struct stm32_tim_priv_s
+{
+ struct stm32_tim_ops_s *ops;
+ stm32_tim_mode_t mode;
+ uint32_t base; /* TIMn base address */
+};
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+/* Get a 16-bit register value by offset */
+
+static inline uint16_t stm32_getreg16(FAR struct stm32_tim_dev_s *dev, uint8_t offset)
+{
+ return getreg16(((struct stm32_tim_priv_s *)dev)->base + offset);
+}
+
+/* Put a 16-bit register value by offset */
+
+static inline void stm32_putreg16(FAR struct stm32_tim_dev_s *dev, uint8_t offset, uint16_t value)
+{
+ putreg16(value, ((struct stm32_tim_priv_s *)dev)->base + offset);
+}
+
+/* Modify a 16-bit register value by offset */
+
+static inline void stm32_modifyreg16(FAR struct stm32_tim_dev_s *dev, uint8_t offset, uint16_t clearbits, uint16_t setbits)
+{
+ modifyreg16(((struct stm32_tim_priv_s *)dev)->base + offset, clearbits, setbits);
+}
+
+/* Get a 32-bit register value by offset. This applies only for the STM32 F4
+ * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5.
+ */
+
+static inline uint32_t stm32_getreg32(FAR struct stm32_tim_dev_s *dev, uint8_t offset)
+{
+ return getreg32(((struct stm32_tim_priv_s *)dev)->base + offset);
+}
+
+/* Put a 32-bit register value by offset. This applies only for the STM32 F4
+ * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5.
+ */
+
+static inline void stm32_putreg32(FAR struct stm32_tim_dev_s *dev, uint8_t offset, uint32_t value)
+{
+ putreg32(value, ((struct stm32_tim_priv_s *)dev)->base + offset);
+}
+
+static void stm32_tim_reload_counter(FAR struct stm32_tim_dev_s *dev)
+{
+ uint16_t val = stm32_getreg16(dev, STM32_BTIM_EGR_OFFSET);
+ val |= ATIM_EGR_UG;
+ stm32_putreg16(dev, STM32_BTIM_EGR_OFFSET, val);
+}
+
+static void stm32_tim_enable(FAR struct stm32_tim_dev_s *dev)
+{
+ uint16_t val = stm32_getreg16(dev, STM32_BTIM_CR1_OFFSET);
+ val |= ATIM_CR1_CEN;
+ stm32_tim_reload_counter(dev);
+ stm32_putreg16(dev, STM32_BTIM_CR1_OFFSET, val);
+}
+
+static void stm32_tim_disable(FAR struct stm32_tim_dev_s *dev)
+{
+ uint16_t val = stm32_getreg16(dev, STM32_BTIM_CR1_OFFSET);
+ val &= ~ATIM_CR1_CEN;
+ stm32_putreg16(dev, STM32_BTIM_CR1_OFFSET, val);
+}
+
+/* Reset timer into system default state, but do not affect output/input pins */
+static void stm32_tim_reset(FAR struct stm32_tim_dev_s *dev)
+{
+ ((struct stm32_tim_priv_s *)dev)->mode = STM32_TIM_MODE_DISABLED;
+ stm32_tim_disable(dev);
+}
+
+static void stm32_tim_gpioconfig(uint32_t cfg, stm32_tim_channel_t mode)
+{
+ /* TODO: Add support for input capture and bipolar dual outputs for TIM8 */
+
+ if (mode & STM32_TIM_CH_MODE_MASK)
+ {
+ stm32_configgpio(cfg);
+ }
+ else
+ {
+ stm32_unconfiggpio(cfg);
+ }
+}
+
+/************************************************************************************
+ * Basic Functions
+ ************************************************************************************/
+
+static int stm32_tim_setclock(FAR struct stm32_tim_dev_s *dev, uint32_t freq)
+{
+ int prescaler;
+
+ ASSERT(dev);
+
+ /* Disable Timer? */
+
+ if (freq == 0)
+ {
+ stm32_tim_disable(dev);
+ return 0;
+ }
+
+#if STM32_NATIM > 0
+ if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM1_BASE ||
+ ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM8_BASE)
+ {
+ prescaler = STM32_TIM18_FREQUENCY / freq;
+ }
+ else
+#endif
+ {
+ prescaler = STM32_TIM27_FREQUENCY / freq;
+ }
+
+ /* We need to decrement value for '1', but only, if we are allowed to
+ * not to cause underflow. Check for overflow.
+ */
+
+ if (prescaler > 0)
+ {
+ prescaler--;
+ }
+
+ if (prescaler > 0xffff)
+ {
+ prescaler = 0xffff;
+ }
+
+ stm32_putreg16(dev, STM32_BTIM_PSC_OFFSET, prescaler);
+ stm32_tim_enable(dev);
+
+ return prescaler;
+}
+
+static void stm32_tim_setperiod(FAR struct stm32_tim_dev_s *dev, uint32_t period)
+{
+ ASSERT(dev);
+ stm32_putreg32(dev, STM32_BTIM_ARR_OFFSET, period);
+}
+
+static int stm32_tim_setisr(FAR struct stm32_tim_dev_s *dev, int (*handler)(int irq, void *context), int source)
+{
+ int vectorno;
+
+ ASSERT(dev);
+ ASSERT(source==0);
+
+ switch (((struct stm32_tim_priv_s *)dev)->base)
+ {
+#if CONFIG_STM32_TIM2
+ case STM32_TIM2_BASE:
+ vectorno = STM32_IRQ_TIM2;
+ break;
+#endif
+#if CONFIG_STM32_TIM3
+ case STM32_TIM3_BASE:
+ vectorno = STM32_IRQ_TIM3;
+ break;
+#endif
+#if CONFIG_STM32_TIM4
+ case STM32_TIM4_BASE:
+ vectorno = STM32_IRQ_TIM4;
+ break;
+#endif
+#if CONFIG_STM32_TIM5
+ case STM32_TIM5_BASE:
+ vectorno = STM32_IRQ_TIM5;
+ break;
+#endif
+#if STM32_NBTIM > 0
+#if CONFIG_STM32_TIM6
+ case STM32_TIM6_BASE:
+ vectorno = STM32_IRQ_TIM6;
+ break;
+#endif
+#endif
+#if STM32_NBTIM > 1
+#if CONFIG_STM32_TIM7
+ case STM32_TIM7_BASE:
+ vectorno = STM32_IRQ_TIM7;
+ break;
+#endif
+#endif
+#if STM32_NATIM > 0
+ /* TODO: add support for multiple sources and callbacks */
+#if CONFIG_STM32_TIM1
+ case STM32_TIM1_BASE:
+ vectorno = STM32_IRQ_TIM1UP;
+ break;
+#endif
+#if CONFIG_STM32_TIM8
+ case STM32_TIM8_BASE:
+ vectorno = STM32_IRQ_TIM8UP;
+ break;
+#endif
+#endif
+ default:
+ return ERROR;
+ }
+
+ /* Disable interrupt when callback is removed */
+
+ if (!handler)
+ {
+ up_disable_irq(vectorno);
+ irq_detach(vectorno);
+ return OK;
+ }
+
+ /* Otherwise set callback and enable interrupt */
+
+ irq_attach(vectorno, handler);
+ up_enable_irq(vectorno);
+//up_prioritize_irq(vectorno, NVIC_SYSH_PRIORITY_DEFAULT);
+ return OK;
+}
+
+static void stm32_tim_enableint(FAR struct stm32_tim_dev_s *dev, int source)
+{
+ ASSERT(dev);
+ stm32_modifyreg16(dev, STM32_BTIM_DIER_OFFSET, 0, ATIM_DIER_UIE);
+}
+
+static void stm32_tim_disableint(FAR struct stm32_tim_dev_s *dev, int source)
+{
+ ASSERT(dev);
+ stm32_modifyreg16(dev, STM32_BTIM_DIER_OFFSET, ATIM_DIER_UIE, 0);
+}
+
+static void stm32_tim_ackint(FAR struct stm32_tim_dev_s *dev, int source)
+{
+ stm32_putreg16(dev, STM32_BTIM_SR_OFFSET, ~ATIM_SR_UIF);
+}
+
+/************************************************************************************
+ * General Functions
+ ************************************************************************************/
+
+static int stm32_tim_setmode(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode)
+{
+ uint16_t val = ATIM_CR1_CEN | ATIM_CR1_ARPE;
+
+ ASSERT(dev);
+
+ /* This function is not supported on basic timers. To enable or
+ * disable it, simply set its clock to valid frequency or zero.
+ */
+
+#if STM32_NBTIM > 0
+ if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM6_BASE
+#endif
+#if STM32_NBTIM > 1
+ || ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM7_BASE
+#endif
+#if STM32_NBTIM > 0
+ )
+ {
+ return ERROR;
+ }
+#endif
+
+ /* Decode operational modes */
+
+ switch (mode & STM32_TIM_MODE_MASK)
+ {
+ case STM32_TIM_MODE_DISABLED:
+ val = 0;
+ break;
+
+ case STM32_TIM_MODE_DOWN:
+ val |= ATIM_CR1_DIR;
+
+ case STM32_TIM_MODE_UP:
+ break;
+
+ case STM32_TIM_MODE_UPDOWN:
+ val |= ATIM_CR1_CENTER1;
+ // Our default: Interrupts are generated on compare, when counting down
+ break;
+
+ case STM32_TIM_MODE_PULSE:
+ val |= ATIM_CR1_OPM;
+ break;
+
+ default: return ERROR;
+ }
+
+ stm32_tim_reload_counter(dev);
+ stm32_putreg16(dev, STM32_BTIM_CR1_OFFSET, val);
+
+#if STM32_NATIM > 0
+ /* Advanced registers require Main Output Enable */
+
+ if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM1_BASE ||
+ ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM8_BASE)
+ {
+ stm32_modifyreg16(dev, STM32_ATIM_BDTR_OFFSET, 0, ATIM_BDTR_MOE);
+ }
+#endif
+
+ return OK;
+}
+
+static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel, stm32_tim_channel_t mode)
+{
+ uint16_t ccmr_val = 0;
+ uint16_t ccer_val = stm32_getreg16(dev, STM32_GTIM_CCER_OFFSET);
+ uint8_t ccmr_offset = STM32_GTIM_CCMR1_OFFSET;
+
+ ASSERT(dev);
+
+ /* Further we use range as 0..3; if channel=0 it will also overflow here */
+
+ if (--channel > 4) return ERROR;
+
+ /* Assume that channel is disabled and polarity is active high */
+
+ ccer_val &= ~(3 << (channel << 2));
+
+ /* This function is not supported on basic timers. To enable or
+ * disable it, simply set its clock to valid frequency or zero.
+ */
+
+#if STM32_NBTIM > 0
+ if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM6_BASE
+#endif
+#if STM32_NBTIM > 1
+ || ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM7_BASE
+#endif
+#if STM32_NBTIM > 0
+ )
+ {
+ return ERROR;
+ }
+#endif
+
+ /* Decode configuration */
+
+ switch (mode & STM32_TIM_CH_MODE_MASK)
+ {
+ case STM32_TIM_CH_DISABLED:
+ break;
+
+ case STM32_TIM_CH_OUTPWM:
+ ccmr_val = (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) + ATIM_CCMR1_OC1PE;
+ ccer_val |= ATIM_CCER_CC1E << (channel << 2);
+ break;
+
+ default:
+ return ERROR;
+ }
+
+ /* Set polarity */
+
+ if (mode & STM32_TIM_CH_POLARITY_NEG)
+ {
+ ccer_val |= ATIM_CCER_CC1P << (channel << 2);
+ }
+
+ /* Define its position (shift) and get register offset */
+
+ if (channel & 1)
+ {
+ ccmr_val <<= 8;
+ }
+
+ if (channel > 1)
+ {
+ ccmr_offset = STM32_GTIM_CCMR2_OFFSET;
+ }
+
+ stm32_putreg16(dev, ccmr_offset, ccmr_val);
+ stm32_putreg16(dev, STM32_GTIM_CCER_OFFSET, ccer_val);
+
+ /* set GPIO */
+
+ switch (((struct stm32_tim_priv_s *)dev)->base)
+ {
+#if CONFIG_STM32_TIM2
+ case STM32_TIM2_BASE:
+ switch (channel)
+ {
+#if defined(GPIO_TIM2_CH1OUT)
+ case 0:
+ stm32_tim_gpioconfig(GPIO_TIM2_CH1OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM2_CH2OUT)
+ case 1:
+ stm32_tim_gpioconfig(GPIO_TIM2_CH2OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM2_CH3OUT)
+ case 2:
+ stm32_tim_gpioconfig(GPIO_TIM2_CH3OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM2_CH4OUT)
+ case 3:
+ stm32_tim_gpioconfig(GPIO_TIM2_CH4OUT, mode);
+ break;
+#endif
+ default:
+ return ERROR;
+ }
+ break;
+#endif
+#if CONFIG_STM32_TIM3
+ case STM32_TIM3_BASE:
+ switch (channel)
+ {
+#if defined(GPIO_TIM3_CH1OUT)
+ case 0:
+ stm32_tim_gpioconfig(GPIO_TIM3_CH1OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM3_CH2OUT)
+ case 1:
+ stm32_tim_gpioconfig(GPIO_TIM3_CH2OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM3_CH3OUT)
+ case 2:
+ stm32_tim_gpioconfig(GPIO_TIM3_CH3OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM3_CH4OUT)
+ case 3:
+ stm32_tim_gpioconfig(GPIO_TIM3_CH4OUT, mode);
+ break;
+#endif
+ default:
+ return ERROR;
+ }
+ break;
+#endif
+#if CONFIG_STM32_TIM4
+ case STM32_TIM4_BASE:
+ switch (channel)
+ {
+#if defined(GPIO_TIM4_CH1OUT)
+ case 0:
+ stm32_tim_gpioconfig(GPIO_TIM4_CH1OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM4_CH2OUT)
+ case 1:
+ stm32_tim_gpioconfig(GPIO_TIM4_CH2OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM4_CH3OUT)
+ case 2:
+ stm32_tim_gpioconfig(GPIO_TIM4_CH3OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM4_CH4OUT)
+ case 3:
+ stm32_tim_gpioconfig(GPIO_TIM4_CH4OUT, mode);
+ break;
+#endif
+ default: return ERROR;
+ }
+ break;
+#endif
+#if CONFIG_STM32_TIM5
+ case STM32_TIM5_BASE:
+ switch (channel)
+ {
+#if defined(GPIO_TIM5_CH1OUT)
+ case 0:
+ stm32_tim_gpioconfig(GPIO_TIM5_CH1OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM5_CH2OUT)
+ case 1:
+ stm32_tim_gpioconfig(GPIO_TIM5_CH2OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM5_CH3OUT)
+ case 2:
+ stm32_tim_gpioconfig(GPIO_TIM5_CH3OUT, mode);
+ break;
+#endif
+#if defined(GPIO_TIM5_CH4OUT)
+ case 3:
+ stm32_tim_gpioconfig(GPIO_TIM5_CH4OUT, mode);
+ break;
+#endif
+ default: return ERROR;
+ }
+ break;
+#endif
+
+#if STM32_NATIM > 0
+#if CONFIG_STM32_TIM1
+ case STM32_TIM1_BASE:
+ switch (channel)
+ {
+#if defined(GPIO_TIM1_CH1OUT)
+ case 0:
+ stm32_tim_gpioconfig(GPIO_TIM1_CH1OUT, mode); break;
+#endif
+#if defined(GPIO_TIM1_CH2OUT)
+ case 1:
+ stm32_tim_gpioconfig(GPIO_TIM1_CH2OUT, mode); break;
+#endif
+#if defined(GPIO_TIM1_CH3OUT)
+ case 2:
+ stm32_tim_gpioconfig(GPIO_TIM1_CH3OUT, mode); break;
+#endif
+#if defined(GPIO_TIM1_CH4OUT)
+ case 3:
+ stm32_tim_gpioconfig(GPIO_TIM1_CH4OUT, mode); break;
+#endif
+ default: return ERROR;
+ }
+ break;
+#endif
+#if CONFIG_STM32_TIM8
+ case STM32_TIM8_BASE:
+ switch (channel)
+ {
+#if defined(GPIO_TIM8_CH1OUT)
+ case 0:
+ stm32_tim_gpioconfig(GPIO_TIM8_CH1OUT, mode); break;
+#endif
+#if defined(GPIO_TIM8_CH2OUT)
+ case 1:
+ stm32_tim_gpioconfig(GPIO_TIM8_CH2OUT, mode); break;
+#endif
+#if defined(GPIO_TIM8_CH3OUT)
+ case 2:
+ stm32_tim_gpioconfig(GPIO_TIM8_CH3OUT, mode); break;
+#endif
+#if defined(GPIO_TIM8_CH4OUT)
+ case 3:
+ stm32_tim_gpioconfig(GPIO_TIM8_CH4OUT, mode); break;
+#endif
+ default:
+ return ERROR;
+ }
+ break;
+#endif
+#endif
+ default:
+ return ERROR;
+ }
+
+ return OK;
+}
+
+static int stm32_tim_setcompare(FAR struct stm32_tim_dev_s *dev, uint8_t channel, uint32_t compare)
+{
+ ASSERT(dev);
+
+ switch (channel)
+ {
+ case 1:
+ stm32_putreg32(dev, STM32_GTIM_CCR1_OFFSET, compare);
+ break;
+ case 2:
+ stm32_putreg32(dev, STM32_GTIM_CCR2_OFFSET, compare);
+ break;
+ case 3:
+ stm32_putreg32(dev, STM32_GTIM_CCR3_OFFSET, compare);
+ break;
+ case 4:
+ stm32_putreg32(dev, STM32_GTIM_CCR4_OFFSET, compare);
+ break;
+ default:
+ return ERROR;
+ }
+ return OK;
+}
+
+static int stm32_tim_getcapture(FAR struct stm32_tim_dev_s *dev, uint8_t channel)
+{
+ ASSERT(dev);
+
+ switch (channel)
+ {
+ case 1:
+ return stm32_getreg32(dev, STM32_GTIM_CCR1_OFFSET);
+ case 2:
+ return stm32_getreg32(dev, STM32_GTIM_CCR2_OFFSET);
+ case 3:
+ return stm32_getreg32(dev, STM32_GTIM_CCR3_OFFSET);
+ case 4:
+ return stm32_getreg32(dev, STM32_GTIM_CCR4_OFFSET);
+ }
+ return ERROR;
+}
+
+/************************************************************************************
+ * Advanced Functions
+ ************************************************************************************/
+
+/* TODO: Advanced functions for the STM32_ATIM */
+
+/************************************************************************************
+ * Device Structures, Instantiation
+ ************************************************************************************/
+
+struct stm32_tim_ops_s stm32_tim_ops =
+{
+ .setmode = &stm32_tim_setmode,
+ .setclock = &stm32_tim_setclock,
+ .setperiod = &stm32_tim_setperiod,
+ .setchannel = &stm32_tim_setchannel,
+ .setcompare = &stm32_tim_setcompare,
+ .getcapture = &stm32_tim_getcapture,
+ .setisr = &stm32_tim_setisr,
+ .enableint = &stm32_tim_enableint,
+ .disableint = &stm32_tim_disableint,
+ .ackint = &stm32_tim_ackint
+};
+
+#if CONFIG_STM32_TIM2
+struct stm32_tim_priv_s stm32_tim2_priv =
+{
+ .ops = &stm32_tim_ops,
+ .mode = STM32_TIM_MODE_UNUSED,
+ .base = STM32_TIM2_BASE,
+};
+#endif
+
+#if CONFIG_STM32_TIM3
+struct stm32_tim_priv_s stm32_tim3_priv =
+{
+ .ops = &stm32_tim_ops,
+ .mode = STM32_TIM_MODE_UNUSED,
+ .base = STM32_TIM3_BASE,
+};
+#endif
+
+#if CONFIG_STM32_TIM4
+struct stm32_tim_priv_s stm32_tim4_priv =
+{
+ .ops = &stm32_tim_ops,
+ .mode = STM32_TIM_MODE_UNUSED,
+ .base = STM32_TIM4_BASE,
+};
+#endif
+
+#if CONFIG_STM32_TIM5
+struct stm32_tim_priv_s stm32_tim5_priv =
+{
+ .ops = &stm32_tim_ops,
+ .mode = STM32_TIM_MODE_UNUSED,
+ .base = STM32_TIM5_BASE,
+};
+#endif
+
+#if STM32_NBTIM > 0
+#if CONFIG_STM32_TIM6
+struct stm32_tim_priv_s stm32_tim6_priv =
+{
+ .ops = &stm32_tim_ops,
+ .mode = STM32_TIM_MODE_UNUSED,
+ .base = STM32_TIM6_BASE,
+};
+#endif
+#endif
+
+#if STM32_NBTIM > 1
+#if CONFIG_STM32_TIM7
+struct stm32_tim_priv_s stm32_tim7_priv =
+{
+ .ops = &stm32_tim_ops,
+ .mode = STM32_TIM_MODE_UNUSED,
+ .base = STM32_TIM7_BASE,
+};
+#endif
+#endif
+
+#if STM32_NATIM > 0
+
+#if CONFIG_STM32_TIM1
+struct stm32_tim_priv_s stm32_tim1_priv =
+{
+ .ops = &stm32_tim_ops,
+ .mode = STM32_TIM_MODE_UNUSED,
+ .base = STM32_TIM1_BASE,
+};
+#endif
+
+#if CONFIG_STM32_TIM8
+struct stm32_tim_priv_s stm32_tim8_priv =
+{
+ .ops = &stm32_tim_ops,
+ .mode = STM32_TIM_MODE_UNUSED,
+ .base = STM32_TIM8_BASE,
+};
+#endif
+
+#endif
+
+/************************************************************************************
+ * Public Function - Initialization
+ ************************************************************************************/
+
+FAR struct stm32_tim_dev_s *stm32_tim_init(int timer)
+{
+ struct stm32_tim_dev_s *dev = NULL;
+
+ /* Get structure and enable power */
+
+ switch (timer)
+ {
+#if CONFIG_STM32_TIM2
+ case 2:
+ dev = (struct stm32_tim_dev_s *)&stm32_tim2_priv;
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM2EN);
+ break;
+#endif
+#if CONFIG_STM32_TIM3
+ case 3:
+ dev = (struct stm32_tim_dev_s *)&stm32_tim3_priv;
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM3EN);
+ break;
+#endif
+#if CONFIG_STM32_TIM4
+ case 4:
+ dev = (struct stm32_tim_dev_s *)&stm32_tim4_priv;
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM4EN);
+ break;
+#endif
+#if CONFIG_STM32_TIM5
+ case 5:
+ dev = (struct stm32_tim_dev_s *)&stm32_tim5_priv;
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM5EN);
+ break;
+#endif
+
+#if STM32_NBTIM > 0
+#if CONFIG_STM32_TIM6
+ case 6:
+ dev = (struct stm32_tim_dev_s *)&stm32_tim6_priv;
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM6EN);
+ break;
+#endif
+#endif
+#if STM32_NBTIM > 1
+#if CONFIG_STM32_TIM7
+ case 7:
+ dev = (struct stm32_tim_dev_s *)&stm32_tim7_priv;
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM7EN);
+ break;
+#endif
+#endif
+
+#if STM32_NATIM > 0
+#if CONFIG_STM32_TIM1
+ case 1:
+ dev = (struct stm32_tim_dev_s *)&stm32_tim1_priv;
+ modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM1EN);
+ break;
+#endif
+#if CONFIG_STM32_TIM8
+ case 8:
+ dev = (struct stm32_tim_dev_s *)&stm32_tim8_priv;
+ modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM8EN);
+ break;
+#endif
+#endif
+ default:
+ return NULL;
+ }
+
+ /* Is device already allocated */
+
+ if (((struct stm32_tim_priv_s *)dev)->mode != STM32_TIM_MODE_UNUSED)
+ {
+ return NULL;
+ }
+
+ stm32_tim_reset(dev);
+
+ return dev;
+}
+
+/* TODO: Detach interrupts, and close down all TIM Channels */
+
+int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev)
+{
+ ASSERT(dev);
+
+ /* Disable power */
+
+ switch (((struct stm32_tim_priv_s *)dev)->base)
+ {
+#if CONFIG_STM32_TIM2
+ case STM32_TIM2_BASE:
+ modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM2EN, 0);
+ break;
+#endif
+#if CONFIG_STM32_TIM3
+ case STM32_TIM3_BASE:
+ modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM3EN, 0);
+ break;
+#endif
+#if CONFIG_STM32_TIM4
+ case STM32_TIM4_BASE:
+ modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM4EN, 0);
+ break;
+#endif
+#if CONFIG_STM32_TIM5
+ case STM32_TIM5_BASE:
+ modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM5EN, 0);
+ break;
+#endif
+#if STM32_NBTIM > 0
+#if CONFIG_STM32_TIM6
+ case STM32_TIM6_BASE:
+ modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM6EN, 0);
+ break;
+#endif
+#endif
+#if STM32_NBTIM > 1
+#if CONFIG_STM32_TIM7
+ case STM32_TIM7_BASE:
+ modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM7EN, 0);
+ break;
+#endif
+#endif
+
+#if STM32_NATIM > 0
+#if CONFIG_STM32_TIM1
+ case STM32_TIM1_BASE:
+ modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM1EN, 0);
+ break;
+#endif
+#if CONFIG_STM32_TIM8
+ case STM32_TIM8_BASE:
+ modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM8EN, 0);
+ break;
+#endif
+#endif
+ default:
+ return ERROR;
+ }
+
+ /* Mark it as free */
+
+ ((struct stm32_tim_priv_s *)dev)->mode = STM32_TIM_MODE_UNUSED;
+
+ return OK;
+}
+
+#endif /* defined(CONFIG_STM32_TIM1 || ... || TIM8) */
diff --git a/nuttx/arch/arm/src/stm32/stm32_tim.h b/nuttx/arch/arm/src/stm32/stm32_tim.h
new file mode 100644
index 000000000..081a3489f
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_tim.h
@@ -0,0 +1,191 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_tim.h
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With modifications and updates by:
+ *
+ * Copyright (C) 2011-2012 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_STM32_STM32_TIM_H
+#define __ARCH_ARM_SRC_STM32_STM32_TIM_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_tim.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Helpers **************************************************************************/
+
+#define STM32_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode))
+#define STM32_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq))
+#define STM32_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period))
+#define STM32_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode))
+#define STM32_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp))
+#define STM32_TIM_GETCAPTURE(d,ch) ((d)->ops->getcapture(d,ch))
+#define STM32_TIM_SETISR(d,hnd,s) ((d)->ops->setisr(d,hnd,s))
+#define STM32_TIM_ENABLEINT(d,s) ((d)->ops->enableint(d,s))
+#define STM32_TIM_DISABLEINT(d,s) ((d)->ops->disableint(d,s))
+#define STM32_TIM_ACKINT(d,s) ((d)->ops->ackint(d,s))
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/* TIM Device Structure */
+
+struct stm32_tim_dev_s
+{
+ struct stm32_tim_ops_s *ops;
+};
+
+/* TIM Modes of Operation */
+
+typedef enum
+{
+ STM32_TIM_MODE_UNUSED = -1,
+
+ /* One of the following */
+
+ STM32_TIM_MODE_MASK = 0x0310,
+ STM32_TIM_MODE_DISABLED = 0x0000,
+ STM32_TIM_MODE_UP = 0x0100,
+ STM32_TIM_MODE_DOWN = 0x0110,
+ STM32_TIM_MODE_UPDOWN = 0x0200,
+ STM32_TIM_MODE_PULSE = 0x0300,
+
+ /* One of the following */
+
+ STM32_TIM_MODE_CK_INT = 0x0000,
+//STM32_TIM_MODE_CK_INT_TRIG = 0x0400,
+//STM32_TIM_MODE_CK_EXT = 0x0800,
+//STM32_TIM_MODE_CK_EXT_TRIG = 0x0C00,
+
+ /* Clock sources, OR'ed with CK_EXT */
+
+//STM32_TIM_MODE_CK_CHINVALID = 0x0000,
+//STM32_TIM_MODE_CK_CH1 = 0x0001,
+//STM32_TIM_MODE_CK_CH2 = 0x0002,
+//STM32_TIM_MODE_CK_CH3 = 0x0003,
+//STM32_TIM_MODE_CK_CH4 = 0x0004
+
+ /* Todo: external trigger block */
+
+} stm32_tim_mode_t;
+
+/* TIM Channel Modes */
+
+typedef enum
+{
+ STM32_TIM_CH_DISABLED = 0x00,
+
+ /* Common configuration */
+
+ STM32_TIM_CH_POLARITY_POS = 0x00,
+ STM32_TIM_CH_POLARITY_NEG = 0x01,
+
+ /* MODES: */
+
+ STM32_TIM_CH_MODE_MASK = 0x06,
+
+ /* Output Compare Modes */
+
+ STM32_TIM_CH_OUTPWM = 0x04, /** Enable standard PWM mode, active high when counter < compare */
+//STM32_TIM_CH_OUTCOMPARE = 0x06,
+
+ // TODO other modes ... as PWM capture, ENCODER and Hall Sensor
+//STM32_TIM_CH_INCAPTURE = 0x10,
+//STM32_TIM_CH_INPWM = 0x20
+//STM32_TIM_CH_DRIVE_OC -- open collector mode
+
+} stm32_tim_channel_t;
+
+/* TIM Operations */
+
+struct stm32_tim_ops_s
+{
+ /* Basic Timers */
+
+ int (*setmode)(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode);
+ int (*setclock)(FAR struct stm32_tim_dev_s *dev, uint32_t freq);
+ void (*setperiod)(FAR struct stm32_tim_dev_s *dev, uint32_t period);
+
+ /* General and Advanced Timers Adds */
+
+ int (*setchannel)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, stm32_tim_channel_t mode);
+ int (*setcompare)(FAR struct stm32_tim_dev_s *dev, uint8_t channel, uint32_t compare);
+ int (*getcapture)(FAR struct stm32_tim_dev_s *dev, uint8_t channel);
+
+ int (*setisr)(FAR struct stm32_tim_dev_s *dev, int (*handler)(int irq, void *context), int source);
+ void (*enableint)(FAR struct stm32_tim_dev_s *dev, int source);
+ void (*disableint)(FAR struct stm32_tim_dev_s *dev, int source);
+ void (*ackint)(FAR struct stm32_tim_dev_s *dev, int source);
+};
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/* Power-up timer and get its structure */
+
+EXTERN FAR struct stm32_tim_dev_s * stm32_tim_init(int timer);
+
+/* Power-down timer, mark it as unused */
+
+EXTERN int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_TIM_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_timerisr.c b/nuttx/arch/arm/src/stm32/stm32_timerisr.c
new file mode 100644
index 000000000..93cca02ac
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_timerisr.c
@@ -0,0 +1,164 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_timerisr.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <time.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "nvic.h"
+#include "clock_internal.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "chip.h"
+#include "stm32_internal.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* The desired timer interrupt frequency is provided by the definition
+ * CLK_TCK (see include/time.h). CLK_TCK defines the desired number of
+ * system clock ticks per second. That value is a user configurable setting
+ * that defaults to 100 (100 ticks per second = 10 MS interval).
+ *
+ * The RCC feeds the Cortex System Timer (SysTick) with the AHB clock (HCLK)
+ * divided by 8. The SysTick can work either with this clock or with the
+ * Cortex clock (HCLK), configurable in the SysTick Control and Status
+ * register.
+ */
+
+#undef CONFIG_STM32_SYSTICK_HCLKd8 /* Power up default is HCLK, not HCLK/8 */
+ /* And I don't know now to re-configure it yet */
+
+#if CONFIG_STM32_SYSTICK_HCLKd8
+# define SYSTICK_RELOAD ((STM32_HCLK_FREQUENCY / 8 / CLK_TCK) - 1)
+#else
+# define SYSTICK_RELOAD ((STM32_HCLK_FREQUENCY / CLK_TCK) - 1)
+#endif
+
+/* The size of the reload field is 24 bits. Verify taht the reload value
+ * will fit in the reload register.
+ */
+
+#if SYSTICK_RELOAD > 0x00ffffff
+# error SYSTICK_RELOAD exceeds the range of the RELOAD register
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global 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_timerinit
+ *
+ * Description:
+ * This function is called during start-up to initialize
+ * the timer interrupt.
+ *
+ ****************************************************************************/
+
+void up_timerinit(void)
+{
+ uint32_t regval;
+
+ /* Set the SysTick interrupt to the default priority */
+
+ regval = getreg32(NVIC_SYSH12_15_PRIORITY);
+ regval &= ~NVIC_SYSH_PRIORITY_PR15_MASK;
+ regval |= (NVIC_SYSH_PRIORITY_DEFAULT << NVIC_SYSH_PRIORITY_PR15_SHIFT);
+ putreg32(regval, NVIC_SYSH12_15_PRIORITY);
+
+ /* Make sure that the SYSTICK clock source is set correctly */
+
+#if 0 /* Does not work. Comes up with HCLK source and I can't change it */
+ regval = getreg32(NVIC_SYSTICK_CTRL);
+#if CONFIG_STM32_SYSTICK_HCLKd8
+ regval &= ~NVIC_SYSTICK_CTRL_CLKSOURCE;
+#else
+ regval |= NVIC_SYSTICK_CTRL_CLKSOURCE;
+#endif
+ putreg32(regval, NVIC_SYSTICK_CTRL);
+#endif
+
+ /* Configure SysTick to interrupt at the requested rate */
+
+ putreg32(SYSTICK_RELOAD, NVIC_SYSTICK_RELOAD);
+
+ /* Attach the timer interrupt vector */
+
+ (void)irq_attach(STM32_IRQ_SYSTICK, (xcpt_t)up_timerisr);
+
+ /* Enable SysTick interrupts */
+
+ putreg32((NVIC_SYSTICK_CTRL_CLKSOURCE|NVIC_SYSTICK_CTRL_TICKINT|NVIC_SYSTICK_CTRL_ENABLE), NVIC_SYSTICK_CTRL);
+
+ /* And enable the timer interrupt */
+
+ up_enable_irq(STM32_IRQ_SYSTICK);
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_uart.h b/nuttx/arch/arm/src/stm32/stm32_uart.h
new file mode 100644
index 000000000..42fe9e346
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_uart.h
@@ -0,0 +1,254 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_uart.h
+ *
+ * Copyright (C) 2009, 2012 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_STC_STM32_STM32_UART_H
+#define __ARCH_ARM_STC_STM32_STM32_UART_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_uart.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Make sure that we have not enabled more U[S]ARTs than are support by
+ * the device.
+ */
+
+#if STM32_NUSART < 6
+# undef CONFIG_STM32_USART6
+#endif
+#if STM32_NUSART < 5
+# undef CONFIG_STM32_UART5
+#endif
+#if STM32_NUSART < 4
+# undef CONFIG_STM32_UART4
+#endif
+#if STM32_NUSART < 3
+# undef CONFIG_STM32_USART3
+#endif
+#if STM32_NUSART < 2
+# undef CONFIG_STM32_USART2
+#endif
+#if STM32_NUSART < 1
+# undef CONFIG_STM32_USART1
+#endif
+
+/* Is there a USART enabled? */
+
+#if defined(CONFIG_STM32_USART1) || defined(CONFIG_STM32_USART2) || \
+ defined(CONFIG_STM32_USART3) || defined(CONFIG_STM32_UART4) || \
+ defined(CONFIG_STM32_UART5) || defined(CONFIG_STM32_USART6)
+# define HAVE_UART 1
+#endif
+
+/* Is there a serial console? */
+
+#if defined(CONFIG_USART1_SERIAL_CONSOLE) && defined(CONFIG_STM32_USART1)
+# undef CONFIG_USART2_SERIAL_CONSOLE
+# undef CONFIG_USART3_SERIAL_CONSOLE
+# undef CONFIG_USART4_SERIAL_CONSOLE
+# undef CONFIG_USART5_SERIAL_CONSOLE
+# undef CONFIG_USART6_SERIAL_CONSOLE
+# define CONSOLE_UART 1
+# define HAVE_CONSOLE 1
+#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_STM32_USART2)
+# undef CONFIG_USART1_SERIAL_CONSOLE
+# undef CONFIG_USART3_SERIAL_CONSOLE
+# undef CONFIG_USART4_SERIAL_CONSOLE
+# undef CONFIG_USART5_SERIAL_CONSOLE
+# undef CONFIG_USART6_SERIAL_CONSOLE
+# define CONSOLE_UART 2
+# define HAVE_CONSOLE 1
+#elif defined(CONFIG_USART3_SERIAL_CONSOLE) && defined(CONFIG_STM32_USART3)
+# undef CONFIG_USART1_SERIAL_CONSOLE
+# undef CONFIG_USART2_SERIAL_CONSOLE
+# undef CONFIG_USART4_SERIAL_CONSOLE
+# undef CONFIG_USART5_SERIAL_CONSOLE
+# undef CONFIG_USART6_SERIAL_CONSOLE
+# define CONSOLE_UART 3
+# define HAVE_CONSOLE 1
+#elif defined(CONFIG_USART4_SERIAL_CONSOLE) && defined(CONFIG_STM32_UART4)
+# undef CONFIG_USART1_SERIAL_CONSOLE
+# undef CONFIG_USART2_SERIAL_CONSOLE
+# undef CONFIG_USART3_SERIAL_CONSOLE
+# undef CONFIG_USART5_SERIAL_CONSOLE
+# undef CONFIG_USART6_SERIAL_CONSOLE
+# define CONSOLE_UART 4
+# define HAVE_CONSOLE 1
+#elif defined(CONFIG_USART5_SERIAL_CONSOLE) && defined(CONFIG_STM32_UART5)
+# undef CONFIG_USART1_SERIAL_CONSOLE
+# undef CONFIG_USART2_SERIAL_CONSOLE
+# undef CONFIG_USART3_SERIAL_CONSOLE
+# undef CONFIG_USART4_SERIAL_CONSOLE
+# undef CONFIG_USART6_SERIAL_CONSOLE
+# define CONSOLE_UART 5
+# define HAVE_CONSOLE 1
+#elif defined(CONFIG_USART6_SERIAL_CONSOLE) && defined(CONFIG_STM32_USART6)
+# undef CONFIG_USART1_SERIAL_CONSOLE
+# undef CONFIG_USART2_SERIAL_CONSOLE
+# undef CONFIG_USART3_SERIAL_CONSOLE
+# undef CONFIG_USART4_SERIAL_CONSOLE
+# undef CONFIG_USART5_SERIAL_CONSOLE
+# define CONSOLE_UART 6
+# define HAVE_CONSOLE 1
+#else
+# undef CONFIG_USART1_SERIAL_CONSOLE
+# undef CONFIG_USART2_SERIAL_CONSOLE
+# undef CONFIG_USART3_SERIAL_CONSOLE
+# undef CONFIG_USART4_SERIAL_CONSOLE
+# undef CONFIG_USART5_SERIAL_CONSOLE
+# undef CONFIG_USART6_SERIAL_CONSOLE
+# define CONSOLE_UART 0
+# undef HAVE_CONSOLE
+#endif
+
+/* DMA support is only provided if CONFIG_ARCH_DMA is in the NuttX configuration.
+ * Furthermore, DMA support is currently only implemented for the F4 (but could be
+ * extended to the F1 and F2 with a little effort in the DMA code.
+ */
+
+#if !defined(HAVE_UART) || !defined(CONFIG_ARCH_DMA) || !defined(CONFIG_STM32_STM32F40XX)
+# undef CONFIG_USART1_RXDMA
+# undef CONFIG_USART2_RXDMA
+# undef CONFIG_USART3_RXDMA
+# undef CONFIG_USART4_RXDMA
+# undef CONFIG_USART5_RXDMA
+# undef CONFIG_USART6_RXDMA
+#endif
+
+/* Disable the DMA configuration on all unused USARTs */
+
+#ifndef CONFIG_STM32_USART1
+# undef CONFIG_USART1_RXDMA
+#endif
+
+#ifndef CONFIG_STM32_USART2
+# undef CONFIG_USART2_RXDMA
+#endif
+
+#ifndef CONFIG_STM32_USART3
+# undef CONFIG_USART3_RXDMA
+#endif
+
+#ifndef CONFIG_STM32_UART4
+# undef CONFIG_USART4_RXDMA
+#endif
+
+#ifndef CONFIG_STM32_UART5
+# undef CONFIG_USART5_RXDMA
+#endif
+
+#ifndef CONFIG_STM32_USART6
+# undef CONFIG_USART6_RXDMA
+#endif
+
+/* Is DMA available on any (enabled) USART? */
+
+#undef SERIAL_HAVE_DMA
+#if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART2_RXDMA) || \
+ defined(CONFIG_USART3_RXDMA) || defined(CONFIG_USART4_RXDMA) || \
+ defined(CONFIG_USART5_RXDMA) || defined(CONFIG_USART6_RXDMA)
+# define SERIAL_HAVE_DMA 1
+#endif
+
+/* Is DMA used on all (enabled) USARTs */
+
+#define SERIAL_HAVE_ONLY_DMA 1
+#if defined(CONFIG_STM32_USART1) && !defined(CONFIG_USART1_RXDMA)
+# undef SERIAL_HAVE_ONLY_DMA
+#elif defined(CONFIG_STM32_USART2) && !defined(CONFIG_USART2_RXDMA)
+# undef SERIAL_HAVE_ONLY_DMA
+#elif defined(CONFIG_STM32_USART3) && !defined(CONFIG_USART3_RXDMA)
+# undef SERIAL_HAVE_ONLY_DMA
+#elif defined(CONFIG_STM32_UART4) && !defined(CONFIG_USART4_RXDMA)
+# undef SERIAL_HAVE_ONLY_DMA
+#elif defined(CONFIG_STM32_UART5) && !defined(CONFIG_USART5_RXDMA)
+# undef SERIAL_HAVE_ONLY_DMA
+#elif defined(CONFIG_STM32_USART6) && !defined(CONFIG_USART6_RXDMA)
+# undef SERIAL_HAVE_ONLY_DMA
+#endif
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_serial_dma_poll
+ *
+ * Description:
+ * Must be called periodically if any STM32 UART is configured for DMA.
+ * The DMA callback is triggered for each fifo size/2 bytes, but this can
+ * result in some bytes being transferred but not collected if the incoming
+ * data is not a whole multiple of half the FIFO size.
+ *
+ * May be safely called from either interrupt or thread context.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_DMA
+EXTERN void stm32_serial_dma_poll(void);
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_STC_STM32_STM32_UART_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_usbdev.c b/nuttx/arch/arm/src/stm32/stm32_usbdev.c
new file mode 100644
index 000000000..602de3824
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_usbdev.c
@@ -0,0 +1,3664 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_usbdev.c
+ *
+ * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.orgr>
+ *
+ * References:
+ * - RM0008 Reference manual, STMicro document ID 13902
+ * - STM32F10xxx USB development kit, UM0424, STMicro
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/usb/usb.h>
+#include <nuttx/usb/usbdev.h>
+#include <nuttx/usb/usbdev_trace.h>
+
+#include <arch/irq.h>
+
+#include "up_arch.h"
+#include "stm32_internal.h"
+#include "stm32_usbdev.h"
+
+#if defined(CONFIG_USBDEV) && defined(CONFIG_STM32_USB)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_USBDEV_EP0_MAXSIZE
+# define CONFIG_USBDEV_EP0_MAXSIZE 64
+#endif
+
+#ifndef CONFIG_USB_PRI
+# define CONFIG_USB_PRI NVIC_SYSH_PRIORITY_DEFAULT
+#endif
+
+/* Extremely detailed register debug that you would normally never want
+ * enabled.
+ */
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_STM32_USBDEV_REGDEBUG
+#endif
+
+/* Initial interrupt mask: Reset + Suspend + Correct Transfer */
+
+#define STM32_CNTR_SETUP (USB_CNTR_RESETM|USB_CNTR_SUSPM|USB_CNTR_CTRM)
+
+/* Endpoint identifiers. The STM32 supports up to 16 mono-directional or 8
+ * bidirectional endpoints. However, when you take into account PMA buffer
+ * usage (see below) and the fact that EP0 is bidirectional, then there is
+ * a functional limitation of EP0 + 5 mono-directional endpoints = 6. We'll
+ * define STM32_NENDPOINTS to be 8, however, because that is how many
+ * endpoint register sets there are.
+ */
+
+#define STM32_NENDPOINTS (8)
+#define EP0 (0)
+#define EP1 (1)
+#define EP2 (2)
+#define EP3 (3)
+#define EP4 (4)
+#define EP5 (5)
+#define EP6 (6)
+#define EP7 (7)
+
+#define STM32_ENDP_BIT(ep) (1 << (ep))
+#define STM32_ENDP_ALLSET 0xff
+
+/* Packet sizes. We us a fixed 64 max packet size for all endpoint types */
+
+#define STM32_MAXPACKET_SHIFT (6)
+#define STM32_MAXPACKET_SIZE (1 << (STM32_MAXPACKET_SHIFT))
+#define STM32_MAXPACKET_MASK (STM32_MAXPACKET_SIZE-1)
+
+#define STM32_EP0MAXPACKET STM32_MAXPACKET_SIZE
+
+/* Buffer descriptor table. We assume that USB has exclusive use of CAN/USB
+ * memory. The buffer table is positioned at the beginning of the 512-byte
+ * CAN/USB memory. We will use the first STM32_NENDPOINTS*4 words for the buffer
+ * table. That is exactly 64 bytes, leaving 7*64 bytes for endpoint buffers.
+ */
+
+#define STM32_BTABLE_ADDRESS (0x00) /* Start at the beginning of USB/CAN RAM */
+#define STM32_DESC_SIZE (8) /* Each descriptor is 4*2=8 bytes in size */
+#define STM32_BTABLE_SIZE (STM32_NENDPOINTS*STM32_DESC_SIZE)
+
+/* Buffer layout. Assume that all buffers are 64-bytes (maxpacketsize), then
+ * we have space for only 7 buffers; endpoint 0 will require two buffers, leaving
+ * 5 for other endpoints.
+ */
+
+#define STM32_BUFFER_START STM32_BTABLE_SIZE
+#define STM32_EP0_RXADDR STM32_BUFFER_START
+#define STM32_EP0_TXADDR (STM32_EP0_RXADDR+STM32_EP0MAXPACKET)
+
+#define STM32_BUFFER_EP0 0x03
+#define STM32_NBUFFERS 7
+#define STM32_BUFFER_BIT(bn) (1 << (bn))
+#define STM32_BUFFER_ALLSET 0x7f
+#define STM32_BUFNO2BUF(bn) (STM32_BUFFER_START+((bn)<<STM32_MAXPACKET_SHIFT))
+
+/* USB-related masks */
+
+#define REQRECIPIENT_MASK (USB_REQ_TYPE_MASK | USB_REQ_RECIPIENT_MASK)
+
+/* Endpoint register masks (handling toggle fields) */
+
+#define EPR_NOTOG_MASK (USB_EPR_CTR_RX | USB_EPR_SETUP | USB_EPR_EPTYPE_MASK |\
+ USB_EPR_EP_KIND | USB_EPR_CTR_TX | USB_EPR_EA_MASK)
+#define EPR_TXDTOG_MASK (USB_EPR_STATTX_MASK | EPR_NOTOG_MASK)
+#define EPR_RXDTOG_MASK (USB_EPR_STATRX_MASK | EPR_NOTOG_MASK)
+
+/* Request queue operations *************************************************/
+
+#define stm32_rqempty(ep) ((ep)->head == NULL)
+#define stm32_rqpeek(ep) ((ep)->head)
+
+/* USB trace ****************************************************************/
+/* Trace error codes */
+
+#define STM32_TRACEERR_ALLOCFAIL 0x0001
+#define STM32_TRACEERR_BADCLEARFEATURE 0x0002
+#define STM32_TRACEERR_BADDEVGETSTATUS 0x0003
+#define STM32_TRACEERR_BADEPGETSTATUS 0x0004
+#define STM32_TRACEERR_BADEPNO 0x0005
+#define STM32_TRACEERR_BADEPTYPE 0x0006
+#define STM32_TRACEERR_BADGETCONFIG 0x0007
+#define STM32_TRACEERR_BADGETSETDESC 0x0008
+#define STM32_TRACEERR_BADGETSTATUS 0x0009
+#define STM32_TRACEERR_BADSETADDRESS 0x000a
+#define STM32_TRACEERR_BADSETCONFIG 0x000b
+#define STM32_TRACEERR_BADSETFEATURE 0x000c
+#define STM32_TRACEERR_BINDFAILED 0x000d
+#define STM32_TRACEERR_DISPATCHSTALL 0x000e
+#define STM32_TRACEERR_DRIVER 0x000f
+#define STM32_TRACEERR_DRIVERREGISTERED 0x0010
+#define STM32_TRACEERR_EP0BADCTR 0x0011
+#define STM32_TRACEERR_EP0SETUPSTALLED 0x0012
+#define STM32_TRACEERR_EPBUFFER 0x0013
+#define STM32_TRACEERR_EPDISABLED 0x0014
+#define STM32_TRACEERR_EPOUTNULLPACKET 0x0015
+#define STM32_TRACEERR_EPRESERVE 0x0016
+#define STM32_TRACEERR_INVALIDCTRLREQ 0x0017
+#define STM32_TRACEERR_INVALIDPARMS 0x0018
+#define STM32_TRACEERR_IRQREGISTRATION 0x0019
+#define STM32_TRACEERR_NOTCONFIGURED 0x001a
+#define STM32_TRACEERR_REQABORTED 0x001b
+
+/* Trace interrupt codes */
+
+#define STM32_TRACEINTID_CLEARFEATURE 0x0001
+#define STM32_TRACEINTID_DEVGETSTATUS 0x0002
+#define STM32_TRACEINTID_DISPATCH 0x0003
+#define STM32_TRACEINTID_EP0IN 0x0004
+#define STM32_TRACEINTID_EP0INDONE 0x0005
+#define STM32_TRACEINTID_EP0OUTDONE 0x0006
+#define STM32_TRACEINTID_EP0SETUPDONE 0x0007
+#define STM32_TRACEINTID_EP0SETUPSETADDRESS 0x0008
+#define STM32_TRACEINTID_EPGETSTATUS 0x0009
+#define STM32_TRACEINTID_EPINDONE 0x000a
+#define STM32_TRACEINTID_EPINQEMPTY 0x000b
+#define STM32_TRACEINTID_EPOUTDONE 0x000c
+#define STM32_TRACEINTID_EPOUTPENDING 0x000d
+#define STM32_TRACEINTID_EPOUTQEMPTY 0x000e
+#define STM32_TRACEINTID_ESOF 0x000f
+#define STM32_TRACEINTID_GETCONFIG 0x0010
+#define STM32_TRACEINTID_GETSETDESC 0x0011
+#define STM32_TRACEINTID_GETSETIF 0x0012
+#define STM32_TRACEINTID_GETSTATUS 0x0013
+#define STM32_TRACEINTID_HPINTERRUPT 0x0014
+#define STM32_TRACEINTID_IFGETSTATUS 0x0015
+#define STM32_TRACEINTID_LPCTR 0x0016
+#define STM32_TRACEINTID_LPINTERRUPT 0x0017
+#define STM32_TRACEINTID_NOSTDREQ 0x0018
+#define STM32_TRACEINTID_RESET 0x0019
+#define STM32_TRACEINTID_SETCONFIG 0x001a
+#define STM32_TRACEINTID_SETFEATURE 0x001b
+#define STM32_TRACEINTID_SUSP 0x001c
+#define STM32_TRACEINTID_SYNCHFRAME 0x001d
+#define STM32_TRACEINTID_WKUP 0x001e
+
+/* Ever-present MIN and MAX macros */
+
+#ifndef MIN
+# define MIN(a,b) (a < b ? a : b)
+#endif
+
+#ifndef MAX
+# define MAX(a,b) (a > b ? a : b)
+#endif
+
+/* Byte ordering in host-based values */
+
+#ifdef CONFIG_ENDIAN_BIG
+# define LSB 1
+# define MSB 0
+#else
+# define LSB 0
+# define MSB 1
+#endif
+
+/****************************************************************************
+ * Private Type Definitions
+ ****************************************************************************/
+
+/* The various states of a control pipe */
+
+enum stm32_devstate_e
+{
+ DEVSTATE_IDLE = 0, /* No request in progress */
+ DEVSTATE_RDREQUEST, /* Read request in progress */
+ DEVSTATE_WRREQUEST, /* Write request in progress */
+ DEVSTATE_STALLED /* We are stalled */
+};
+
+/* Resume states */
+
+enum stm32_rsmstate_e
+{
+ RSMSTATE_IDLE = 0, /* Device is either fully suspended or running */
+ RSMSTATE_STARTED, /* Resume sequence has been started */
+ RSMSTATE_WAITING /* Waiting (on ESOFs) for end of sequence */
+};
+
+union wb_u
+{
+ uint16_t w;
+ uint8_t b[2];
+};
+
+/* A container for a request so that the request make be retained in a list */
+
+struct stm32_req_s
+{
+ struct usbdev_req_s req; /* Standard USB request */
+ struct stm32_req_s *flink; /* Supports a singly linked list */
+};
+
+/* This is the internal representation of an endpoint */
+
+struct stm32_ep_s
+{
+ /* Common endpoint fields. This must be the first thing defined in the
+ * structure so that it is possible to simply cast from struct usbdev_ep_s
+ * to struct stm32_ep_s.
+ */
+
+ struct usbdev_ep_s ep; /* Standard endpoint structure */
+
+ /* STR71X-specific fields */
+
+ struct stm32_usbdev_s *dev; /* Reference to private driver data */
+ struct stm32_req_s *head; /* Request list for this endpoint */
+ struct stm32_req_s *tail;
+ uint8_t bufno; /* Allocated buffer number */
+ uint8_t stalled:1; /* true: Endpoint is stalled */
+ uint8_t halted:1; /* true: Endpoint feature halted */
+ uint8_t txbusy:1; /* true: TX endpoint FIFO full */
+ uint8_t txnullpkt:1; /* Null packet needed at end of transfer */
+};
+
+struct stm32_usbdev_s
+{
+ /* Common device fields. This must be the first thing defined in the
+ * structure so that it is possible to simply cast from struct usbdev_s
+ * to structstm32_usbdev_s.
+ */
+
+ struct usbdev_s usbdev;
+
+ /* The bound device class driver */
+
+ struct usbdevclass_driver_s *driver;
+
+ /* STM32-specific fields */
+
+ struct usb_ctrlreq_s ctrl; /* Last EP0 request */
+ uint8_t devstate; /* Driver state (see enum stm32_devstate_e) */
+ uint8_t rsmstate; /* Resume state (see enum stm32_rsmstate_e) */
+ uint8_t nesofs; /* ESOF counter (for resume support) */
+ uint8_t rxpending:1; /* 1: OUT data in PMA, but no read requests */
+ uint8_t selfpowered:1; /* 1: Device is self powered */
+ uint8_t epavail; /* Bitset of available endpoints */
+ uint8_t bufavail; /* Bitset of available buffers */
+ uint16_t rxstatus; /* Saved during interrupt processing */
+ uint16_t txstatus; /* " " " " " " " " */
+ uint16_t imask; /* Current interrupt mask */
+
+ /* The endpoint list */
+
+ struct stm32_ep_s eplist[STM32_NENDPOINTS];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Register operations ******************************************************/
+
+#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint16_t stm32_getreg(uint32_t addr);
+static void stm32_putreg(uint16_t val, uint32_t addr);
+static void stm32_checksetup(void);
+static void stm32_dumpep(int epno);
+#else
+# define stm32_getreg(addr) getreg16(addr)
+# define stm32_putreg(val,addr) putreg16(val,addr)
+# define stm32_checksetup()
+# define stm32_dumpep(epno)
+#endif
+
+/* Low-Level Helpers ********************************************************/
+
+static inline void
+ stm32_seteptxcount(uint8_t epno, uint16_t count);
+static inline void
+ stm32_seteptxaddr(uint8_t epno, uint16_t addr);
+static inline uint16_t
+ stm32_geteptxaddr(uint8_t epno);
+static void stm32_seteprxcount(uint8_t epno, uint16_t count);
+static inline uint16_t
+ stm32_geteprxcount(uint8_t epno);
+static inline void
+ stm32_seteprxaddr(uint8_t epno, uint16_t addr);
+static inline uint16_t
+ stm32_geteprxaddr(uint8_t epno);
+static inline void
+ stm32_setepaddress(uint8_t epno, uint16_t addr);
+static inline void
+ stm32_seteptype(uint8_t epno, uint16_t type);
+static inline void
+ stm32_seteptxaddr(uint8_t epno, uint16_t addr);
+static inline void
+ stm32_setstatusout(uint8_t epno);
+static inline void
+ stm32_clrstatusout(uint8_t epno);
+static void stm32_clrrxdtog(uint8_t epno);
+static void stm32_clrtxdtog(uint8_t epno);
+static void stm32_clrepctrrx(uint8_t epno);
+static void stm32_clrepctrtx(uint8_t epno);
+static void stm32_seteptxstatus(uint8_t epno, uint16_t state);
+static void stm32_seteprxstatus(uint8_t epno, uint16_t state);
+static inline uint16_t
+ stm32_geteptxstatus(uint8_t epno);
+static inline uint16_t
+ stm32_geteprxstatus(uint8_t epno);
+static bool stm32_eptxstalled(uint8_t epno);
+static bool stm32_eprxstalled(uint8_t epno);
+static void stm32_setimask(struct stm32_usbdev_s *priv, uint16_t setbits,
+ uint16_t clrbits);
+
+/* Suspend/Resume Helpers ***************************************************/
+
+static void stm32_suspend(struct stm32_usbdev_s *priv);
+static void stm32_initresume(struct stm32_usbdev_s *priv);
+static void stm32_esofpoll(struct stm32_usbdev_s *priv) ;
+
+/* Request Helpers **********************************************************/
+
+static void stm32_copytopma(const uint8_t *buffer, uint16_t pma,
+ uint16_t nbytes);
+static inline void
+ stm32_copyfrompma(uint8_t *buffer, uint16_t pma, uint16_t nbytes);
+static struct stm32_req_s *
+ stm32_rqdequeue(struct stm32_ep_s *privep);
+static void stm32_rqenqueue(struct stm32_ep_s *privep,
+ struct stm32_req_s *req);
+static inline void
+ stm32_abortrequest(struct stm32_ep_s *privep,
+ struct stm32_req_s *privreq, int16_t result);
+static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result);
+static void stm32_epwrite(struct stm32_usbdev_s *buf,
+ struct stm32_ep_s *privep, const uint8_t *data, uint32_t nbytes);
+static int stm32_wrrequest(struct stm32_usbdev_s *priv,
+ struct stm32_ep_s *privep);
+static int stm32_rdrequest(struct stm32_usbdev_s *priv,
+ struct stm32_ep_s *privep);
+static void stm32_cancelrequests(struct stm32_ep_s *privep);
+
+/* Interrupt level processing ***********************************************/
+
+static void stm32_dispatchrequest(struct stm32_usbdev_s *priv);
+static void stm32_epdone(struct stm32_usbdev_s *priv, uint8_t epno);
+static void stm32_setdevaddr(struct stm32_usbdev_s *priv, uint8_t value);
+static void stm32_ep0setup(struct stm32_usbdev_s *priv);
+static void stm32_ep0out(struct stm32_usbdev_s *priv);
+static void stm32_ep0in(struct stm32_usbdev_s *priv);
+static inline void
+ stm32_ep0done(struct stm32_usbdev_s *priv, uint16_t istr);
+static void stm32_lptransfer(struct stm32_usbdev_s *priv);
+static int stm32_hpinterrupt(int irq, void *context);
+static int stm32_lpinterrupt(int irq, void *context);
+
+/* Endpoint helpers *********************************************************/
+
+static inline struct stm32_ep_s *
+ stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset);
+static inline void
+ stm32_epunreserve(struct stm32_usbdev_s *priv,
+ struct stm32_ep_s *privep);
+static inline bool
+ stm32_epreserved(struct stm32_usbdev_s *priv, int epno);
+static int stm32_epallocpma(struct stm32_usbdev_s *priv);
+static inline void
+ stm32_epfreepma(struct stm32_usbdev_s *priv,
+ struct stm32_ep_s *privep);
+
+/* Endpoint operations ******************************************************/
+
+static int stm32_epconfigure(struct usbdev_ep_s *ep,
+ const struct usb_epdesc_s *desc, bool last);
+static int stm32_epdisable(struct usbdev_ep_s *ep);
+static struct usbdev_req_s *
+ stm32_epallocreq(struct usbdev_ep_s *ep);
+static void stm32_epfreereq(struct usbdev_ep_s *ep,
+ struct usbdev_req_s *);
+static int stm32_epsubmit(struct usbdev_ep_s *ep,
+ struct usbdev_req_s *req);
+static int stm32_epcancel(struct usbdev_ep_s *ep,
+ struct usbdev_req_s *req);
+static int stm32_epstall(struct usbdev_ep_s *ep, bool resume);
+
+/* USB device controller operations *****************************************/
+
+static struct usbdev_ep_s *
+ stm32_allocep(struct usbdev_s *dev, uint8_t epno, bool in,
+ uint8_t eptype);
+static void stm32_freeep(struct usbdev_s *dev, struct usbdev_ep_s *ep);
+static int stm32_getframe(struct usbdev_s *dev);
+static int stm32_wakeup(struct usbdev_s *dev);
+static int stm32_selfpowered(struct usbdev_s *dev, bool selfpowered);
+
+/* Initialization/Reset *****************************************************/
+
+static void stm32_reset(struct stm32_usbdev_s *priv);
+static void stm32_hwreset(struct stm32_usbdev_s *priv);
+static void stm32_hwsetup(struct stm32_usbdev_s *priv);
+static void stm32_hwshutdown(struct stm32_usbdev_s *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Since there is only a single USB interface, all status information can be
+ * be simply retained in a single global instance.
+ */
+
+static struct stm32_usbdev_s g_usbdev;
+
+static const struct usbdev_epops_s g_epops =
+{
+ .configure = stm32_epconfigure,
+ .disable = stm32_epdisable,
+ .allocreq = stm32_epallocreq,
+ .freereq = stm32_epfreereq,
+ .submit = stm32_epsubmit,
+ .cancel = stm32_epcancel,
+ .stall = stm32_epstall,
+};
+
+static const struct usbdev_ops_s g_devops =
+{
+ .allocep = stm32_allocep,
+ .freeep = stm32_freeep,
+ .getframe = stm32_getframe,
+ .wakeup = stm32_wakeup,
+ .selfpowered = stm32_selfpowered,
+ .pullup = stm32_usbpullup,
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Register Operations
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_getreg
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint16_t stm32_getreg(uint32_t addr)
+{
+ static uint32_t prevaddr = 0;
+ static uint16_t preval = 0;
+ static uint32_t count = 0;
+
+ /* Read the value from the register */
+
+ uint16_t val = getreg16(addr);
+
+ /* Is this the same value that we read from the same register last time?
+ * Are we polling the register? If so, suppress some of the output.
+ */
+
+ if (addr == prevaddr && val == preval)
+ {
+ if (count == 0xffffffff || ++count > 3)
+ {
+ if (count == 4)
+ {
+ lldbg("...\n");
+ }
+ return val;
+ }
+ }
+
+ /* No this is a new address or value */
+
+ else
+ {
+ /* Did we print "..." for the previous value? */
+
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
+
+ lldbg("[repeats %d more times]\n", count-3);
+ }
+
+ /* Save the new address, value, and count */
+
+ prevaddr = addr;
+ preval = val;
+ count = 1;
+ }
+
+ /* Show the register value read */
+
+ lldbg("%08x->%04x\n", addr, val);
+ return val;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_putreg
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static void stm32_putreg(uint16_t val, uint32_t addr)
+{
+ /* Show the register value being written */
+
+ lldbg("%08x<-%04x\n", addr, val);
+
+ /* Write the value */
+
+ putreg16(val, addr);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_dumpep
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static void stm32_dumpep(int epno)
+{
+ uint32_t addr;
+
+ /* Common registers */
+
+ lldbg("CNTR: %04x\n", getreg16(STM32_USB_CNTR));
+ lldbg("ISTR: %04x\n", getreg16(STM32_USB_ISTR));
+ lldbg("FNR: %04x\n", getreg16(STM32_USB_FNR));
+ lldbg("DADDR: %04x\n", getreg16(STM32_USB_DADDR));
+ lldbg("BTABLE: %04x\n", getreg16(STM32_USB_BTABLE));
+
+ /* Endpoint register */
+
+ addr = STM32_USB_EPR(epno);
+ lldbg("EPR%d: [%08x] %04x\n", epno, addr, getreg16(addr));
+
+ /* Endpoint descriptor */
+
+ addr = STM32_USB_BTABLE_ADDR(epno, 0);
+ lldbg("DESC: %08x\n", addr);
+
+ /* Endpoint buffer descriptor */
+
+ addr = STM32_USB_ADDR_TX(epno);
+ lldbg(" TX ADDR: [%08x] %04x\n", addr, getreg16(addr));
+
+ addr = STM32_USB_COUNT_TX(epno);
+ lldbg(" COUNT: [%08x] %04x\n", addr, getreg16(addr));
+
+ addr = STM32_USB_ADDR_RX(epno);
+ lldbg(" RX ADDR: [%08x] %04x\n", addr, getreg16(addr));
+
+ addr = STM32_USB_COUNT_RX(epno);
+ lldbg(" COUNT: [%08x] %04x\n", addr, getreg16(addr));
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_checksetup
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static void stm32_checksetup(void)
+{
+ uint32_t cfgr = getreg32(STM32_RCC_CFGR);
+ uint32_t apb1rstr = getreg32(STM32_RCC_APB1RSTR);
+ uint32_t apb1enr = getreg32(STM32_RCC_APB1ENR);
+
+ lldbg("CFGR: %08x APB1RSTR: %08x APB1ENR: %08x\n", cfgr, apb1rstr, apb1enr);
+
+ if ((apb1rstr & RCC_APB1RSTR_USBRST) != 0 ||
+ (apb1enr & RCC_APB1ENR_USBEN) == 0)
+ {
+ lldbg("ERROR: USB is NOT setup correctly\n");
+ }
+}
+#endif
+
+/****************************************************************************
+ * Low-Level Helpers
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_seteptxcount
+ ****************************************************************************/
+
+static inline void stm32_seteptxcount(uint8_t epno, uint16_t count)
+{
+ volatile uint32_t *epaddr = (uint32_t*)STM32_USB_COUNT_TX(epno);
+ *epaddr = count;
+}
+
+/****************************************************************************
+ * Name: stm32_seteptxaddr
+ ****************************************************************************/
+
+static inline void stm32_seteptxaddr(uint8_t epno, uint16_t addr)
+{
+ volatile uint32_t *txaddr = (uint32_t*)STM32_USB_ADDR_TX(epno);
+ *txaddr = addr;
+}
+
+/****************************************************************************
+ * Name: stm32_geteptxaddr
+ ****************************************************************************/
+
+static inline uint16_t stm32_geteptxaddr(uint8_t epno)
+{
+ volatile uint32_t *txaddr = (uint32_t*)STM32_USB_ADDR_TX(epno);
+ return (uint16_t)*txaddr;
+}
+
+/****************************************************************************
+ * Name: stm32_seteprxcount
+ ****************************************************************************/
+
+static void stm32_seteprxcount(uint8_t epno, uint16_t count)
+{
+ volatile uint32_t *epaddr = (uint32_t*)STM32_USB_COUNT_RX(epno);
+ uint32_t rxcount = 0;
+ uint16_t nblocks;
+
+ /* The upper bits of the RX COUNT value contain the size of allocated
+ * RX buffer. This is based on a block size of 2 or 32:
+ *
+ * USB_COUNT_RX_BL_SIZE not set:
+ * nblocks is in units of 2 bytes.
+ * 00000 - not allowed
+ * 00001 - 2 bytes
+ * ....
+ * 11111 - 62 bytes
+ *
+ * USB_COUNT_RX_BL_SIZE set:
+ * 00000 - 32 bytes
+ * 00001 - 64 bytes
+ * ...
+ * 01111 - 512 bytes
+ * 1xxxx - Not allowed
+ */
+
+ if (count > 62)
+ {
+ /* Blocks of 32 (with 0 meaning one block of 32) */
+
+ nblocks = (count >> 5) - 1 ;
+ DEBUGASSERT(nblocks <= 0x0f);
+ rxcount = (uint32_t)((nblocks << USB_COUNT_RX_NUM_BLOCK_SHIFT) | USB_COUNT_RX_BL_SIZE);
+ }
+ else if (count > 0)
+ {
+ /* Blocks of 2 (with 1 meaning one block of 2) */
+
+ nblocks = (count + 1) >> 1;
+ DEBUGASSERT(nblocks > 0 && nblocks < 0x1f);
+ rxcount = (uint32_t)(nblocks << USB_COUNT_RX_NUM_BLOCK_SHIFT);
+ }
+ *epaddr = rxcount;
+}
+
+/****************************************************************************
+ * Name: stm32_geteprxcount
+ ****************************************************************************/
+
+static inline uint16_t stm32_geteprxcount(uint8_t epno)
+{
+ volatile uint32_t *epaddr = (uint32_t*)STM32_USB_COUNT_RX(epno);
+ return (*epaddr) & USB_COUNT_RX_MASK;
+}
+
+/****************************************************************************
+ * Name: stm32_seteprxaddr
+ ****************************************************************************/
+
+static inline void stm32_seteprxaddr(uint8_t epno, uint16_t addr)
+{
+ volatile uint32_t *rxaddr = (uint32_t*)STM32_USB_ADDR_RX(epno);
+ *rxaddr = addr;
+}
+
+/****************************************************************************
+ * Name: stm32_seteprxaddr
+ ****************************************************************************/
+
+static inline uint16_t stm32_geteprxaddr(uint8_t epno)
+{
+ volatile uint32_t *rxaddr = (uint32_t*)STM32_USB_ADDR_RX(epno);
+ return (uint16_t)*rxaddr;
+}
+
+/****************************************************************************
+ * Name: stm32_setepaddress
+ ****************************************************************************/
+
+static inline void stm32_setepaddress(uint8_t epno, uint16_t addr)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ regval = stm32_getreg(epaddr);
+ regval &= EPR_NOTOG_MASK;
+ regval &= ~USB_EPR_EA_MASK;
+ regval |= (addr << USB_EPR_EA_SHIFT);
+ stm32_putreg(regval, epaddr);
+}
+
+/****************************************************************************
+ * Name: stm32_seteptype
+ ****************************************************************************/
+
+static inline void stm32_seteptype(uint8_t epno, uint16_t type)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ regval = stm32_getreg(epaddr);
+ regval &= EPR_NOTOG_MASK;
+ regval &= ~USB_EPR_EPTYPE_MASK;
+ regval |= type;
+ stm32_putreg(regval, epaddr);
+}
+
+/****************************************************************************
+ * Name: stm32_setstatusout
+ ****************************************************************************/
+
+static inline void stm32_setstatusout(uint8_t epno)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ /* For a BULK endpoint the EP_KIND bit is used to enabled double buffering;
+ * for a CONTROL endpoint, it is set to indicate that a status OUT
+ * transaction is expected. The bit is not used with out endpoint types.
+ */
+
+ regval = stm32_getreg(epaddr);
+ regval &= EPR_NOTOG_MASK;
+ regval |= USB_EPR_EP_KIND;
+ stm32_putreg(regval, epaddr);
+}
+
+/****************************************************************************
+ * Name: stm32_clrstatusout
+ ****************************************************************************/
+
+static inline void stm32_clrstatusout(uint8_t epno)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ /* For a BULK endpoint the EP_KIND bit is used to enabled double buffering;
+ * for a CONTROL endpoint, it is set to indicate that a status OUT
+ * transaction is expected. The bit is not used with out endpoint types.
+ */
+
+ regval = stm32_getreg(epaddr);
+ regval &= EPR_NOTOG_MASK;
+ regval &= ~USB_EPR_EP_KIND;
+ stm32_putreg(regval, epaddr);
+}
+
+/****************************************************************************
+ * Name: stm32_clrrxdtog
+ ****************************************************************************/
+
+static void stm32_clrrxdtog(uint8_t epno)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ regval = stm32_getreg(epaddr);
+ if ((regval & USB_EPR_DTOG_RX) != 0)
+ {
+ regval &= EPR_NOTOG_MASK;
+ regval |= USB_EPR_DTOG_RX;
+ stm32_putreg(regval, epaddr);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_clrtxdtog
+ ****************************************************************************/
+
+static void stm32_clrtxdtog(uint8_t epno)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ regval = stm32_getreg(epaddr);
+ if ((regval & USB_EPR_DTOG_TX) != 0)
+ {
+ regval &= EPR_NOTOG_MASK;
+ regval |= USB_EPR_DTOG_TX;
+ stm32_putreg(regval, epaddr);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_clrepctrrx
+ ****************************************************************************/
+
+static void stm32_clrepctrrx(uint8_t epno)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ regval = stm32_getreg(epaddr);
+ regval &= EPR_NOTOG_MASK;
+ regval &= ~USB_EPR_CTR_RX;
+ stm32_putreg(regval, epaddr);
+}
+
+/****************************************************************************
+ * Name: stm32_clrepctrtx
+ ****************************************************************************/
+
+static void stm32_clrepctrtx(uint8_t epno)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ regval = stm32_getreg(epaddr);
+ regval &= EPR_NOTOG_MASK;
+ regval &= ~USB_EPR_CTR_TX;
+ stm32_putreg(regval, epaddr);
+}
+
+/****************************************************************************
+ * Name: stm32_geteptxstatus
+ ****************************************************************************/
+
+static inline uint16_t stm32_geteptxstatus(uint8_t epno)
+{
+ return (uint16_t)(stm32_getreg(STM32_USB_EPR(epno)) & USB_EPR_STATTX_MASK);
+}
+
+/****************************************************************************
+ * Name: stm32_geteprxstatus
+ ****************************************************************************/
+
+static inline uint16_t stm32_geteprxstatus(uint8_t epno)
+{
+ return (stm32_getreg(STM32_USB_EPR(epno)) & USB_EPR_STATRX_MASK);
+}
+
+/****************************************************************************
+ * Name: stm32_seteptxstatus
+ ****************************************************************************/
+
+static void stm32_seteptxstatus(uint8_t epno, uint16_t state)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ /* The bits in the STAT_TX field can be toggled by software to set their
+ * value. When set to 0, the value remains unchanged; when set to one,
+ * value toggles.
+ */
+
+ regval = stm32_getreg(epaddr);
+
+ /* The exclusive OR will set STAT_TX bits to 1 if there value is different
+ * from the bits requested in 'state'
+ */
+
+ regval ^= state;
+ regval &= EPR_TXDTOG_MASK;
+ stm32_putreg(regval, epaddr);
+}
+
+/****************************************************************************
+ * Name: stm32_seteprxstatus
+ ****************************************************************************/
+
+static void stm32_seteprxstatus(uint8_t epno, uint16_t state)
+{
+ uint32_t epaddr = STM32_USB_EPR(epno);
+ uint16_t regval;
+
+ /* The bits in the STAT_RX field can be toggled by software to set their
+ * value. When set to 0, the value remains unchanged; when set to one,
+ * value toggles.
+ */
+
+ regval = stm32_getreg(epaddr);
+
+ /* The exclusive OR will set STAT_RX bits to 1 if there value is different
+ * from the bits requested in 'state'
+ */
+
+ regval ^= state;
+ regval &= EPR_RXDTOG_MASK;
+ stm32_putreg(regval, epaddr);
+}
+
+/****************************************************************************
+ * Name: stm32_eptxstalled
+ ****************************************************************************/
+
+static inline bool stm32_eptxstalled(uint8_t epno)
+{
+ return (stm32_geteptxstatus(epno) == USB_EPR_STATTX_STALL);
+}
+
+/****************************************************************************
+ * Name: stm32_eprxstalled
+ ****************************************************************************/
+
+static inline bool stm32_eprxstalled(uint8_t epno)
+{
+ return (stm32_geteprxstatus(epno) == USB_EPR_STATRX_STALL);
+}
+
+/****************************************************************************
+ * Request Helpers
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_copytopma
+ ****************************************************************************/
+
+static void stm32_copytopma(const uint8_t *buffer, uint16_t pma, uint16_t nbytes)
+{
+ uint16_t *dest;
+ uint16_t ms;
+ uint16_t ls;
+ int nwords = (nbytes + 1) >> 1;
+ int i;
+
+ /* Copy loop. Source=user buffer, Dest=packet memory */
+
+ dest = (uint16_t*)(STM32_USBCANRAM_BASE + ((uint32_t)pma << 1));
+ for (i = nwords; i != 0; i--)
+ {
+ /* Read two bytes and pack into on 16-bit word */
+
+ ls = (uint16_t)(*buffer++);
+ ms = (uint16_t)(*buffer++);
+ *dest = ms << 8 | ls;
+
+ /* Source address increments by 2*sizeof(uint8_t) = 2; Dest address
+ * increments by 2*sizeof(uint16_t) = 4.
+ */
+
+ dest += 2;
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_copyfrompma
+ ****************************************************************************/
+
+static inline void
+stm32_copyfrompma(uint8_t *buffer, uint16_t pma, uint16_t nbytes)
+{
+ uint32_t *src;
+ int nwords = (nbytes + 1) >> 1;
+ int i;
+
+ /* Copy loop. Source=packet memory, Dest=user buffer */
+
+ src = (uint32_t*)(STM32_USBCANRAM_BASE + ((uint32_t)pma << 1));
+ for (i = nwords; i != 0; i--)
+ {
+ /* Copy 16-bits from packet memory to user buffer. */
+
+ *(uint16_t*)buffer = *src++;
+
+ /* Source address increments by 1*sizeof(uint32_t) = 4; Dest address
+ * increments by 2*sizeof(uint8_t) = 2.
+ */
+
+ buffer += 2;
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_rqdequeue
+ ****************************************************************************/
+
+static struct stm32_req_s *stm32_rqdequeue(struct stm32_ep_s *privep)
+{
+ struct stm32_req_s *ret = privep->head;
+
+ if (ret)
+ {
+ privep->head = ret->flink;
+ if (!privep->head)
+ {
+ privep->tail = NULL;
+ }
+
+ ret->flink = NULL;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: stm32_rqenqueue
+ ****************************************************************************/
+
+static void stm32_rqenqueue(struct stm32_ep_s *privep, struct stm32_req_s *req)
+{
+ req->flink = NULL;
+ if (!privep->head)
+ {
+ privep->head = req;
+ privep->tail = req;
+ }
+ else
+ {
+ privep->tail->flink = req;
+ privep->tail = req;
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_abortrequest
+ ****************************************************************************/
+
+static inline void
+stm32_abortrequest(struct stm32_ep_s *privep, struct stm32_req_s *privreq, int16_t result)
+{
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_REQABORTED), (uint16_t)USB_EPNO(privep->ep.eplog));
+
+ /* Save the result in the request structure */
+
+ privreq->req.result = result;
+
+ /* Callback to the request completion handler */
+
+ privreq->req.callback(&privep->ep, &privreq->req);
+}
+
+/****************************************************************************
+ * Name: stm32_reqcomplete
+ ****************************************************************************/
+
+static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result)
+{
+ struct stm32_req_s *privreq;
+ irqstate_t flags;
+
+ /* Remove the completed request at the head of the endpoint request list */
+
+ flags = irqsave();
+ privreq = stm32_rqdequeue(privep);
+ irqrestore(flags);
+
+ if (privreq)
+ {
+ /* If endpoint 0, temporarily reflect the state of protocol stalled
+ * in the callback.
+ */
+
+ bool stalled = privep->stalled;
+ if (USB_EPNO(privep->ep.eplog) == EP0)
+ {
+ privep->stalled = (privep->dev->devstate == DEVSTATE_STALLED);
+ }
+
+ /* Save the result in the request structure */
+
+ privreq->req.result = result;
+
+ /* Callback to the request completion handler */
+
+ privreq->flink = NULL;
+ privreq->req.callback(&privep->ep, &privreq->req);
+
+ /* Restore the stalled indication */
+
+ privep->stalled = stalled;
+ }
+}
+
+/****************************************************************************
+ * Name: tm32_epwrite
+ ****************************************************************************/
+
+static void stm32_epwrite(struct stm32_usbdev_s *priv,
+ struct stm32_ep_s *privep,
+ const uint8_t *buf, uint32_t nbytes)
+{
+ uint8_t epno = USB_EPNO(privep->ep.eplog);
+ usbtrace(TRACE_WRITE(epno), nbytes);
+
+ /* Check for a zero-length packet */
+
+ if (nbytes > 0)
+ {
+ /* Copy the data from the user buffer into packet memory for this
+ * endpoint
+ */
+
+ stm32_copytopma(buf, stm32_geteptxaddr(epno), nbytes);
+ }
+
+ /* Send the packet (might be a null packet nbytes == 0) */
+
+ stm32_seteptxcount(epno, nbytes);
+ priv->txstatus = USB_EPR_STATTX_VALID;
+
+ /* Indicate that there is data in the TX packet memory. This will be cleared
+ * when the next data out interrupt is received.
+ */
+
+ privep->txbusy = true;
+}
+
+/****************************************************************************
+ * Name: stm32_wrrequest
+ ****************************************************************************/
+
+static int stm32_wrrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
+{
+ struct stm32_req_s *privreq;
+ uint8_t *buf;
+ uint8_t epno;
+ int nbytes;
+ int bytesleft;
+
+ /* We get here when an IN endpoint interrupt occurs. So now we know that
+ * there is no TX transfer in progress.
+ */
+
+ privep->txbusy = false;
+
+ /* Check the request from the head of the endpoint request queue */
+
+ privreq = stm32_rqpeek(privep);
+ if (!privreq)
+ {
+ /* There is no TX transfer in progress and no new pending TX
+ * requests to send.
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPINQEMPTY), 0);
+ priv->devstate = DEVSTATE_IDLE;
+ return OK;
+ }
+
+ epno = USB_EPNO(privep->ep.eplog);
+ ullvdbg("epno=%d req=%p: len=%d xfrd=%d nullpkt=%d\n",
+ epno, privreq, privreq->req.len, privreq->req.xfrd, privep->txnullpkt);
+
+ /* Get the number of bytes left to be sent in the packet */
+
+ bytesleft = privreq->req.len - privreq->req.xfrd;
+ nbytes = bytesleft;
+
+#warning "REVISIT: If the EP supports double buffering, then we can do better"
+
+ /* Send the next packet */
+
+ if (nbytes > 0)
+ {
+ /* Either send the maxpacketsize or all of the remaining data in
+ * the request.
+ */
+
+ privep->txnullpkt = 0;
+ if (nbytes >= privep->ep.maxpacket)
+ {
+ nbytes = privep->ep.maxpacket;
+
+ /* Handle the case where this packet is exactly the
+ * maxpacketsize. Do we need to send a zero-length packet
+ * in this case?
+ */
+
+ if (bytesleft == privep->ep.maxpacket &&
+ (privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0)
+ {
+ privep->txnullpkt = 1;
+ }
+ }
+ }
+
+ /* Send the packet (might be a null packet nbytes == 0) */
+
+ buf = privreq->req.buf + privreq->req.xfrd;
+ stm32_epwrite(priv, privep, buf, nbytes);
+ priv->devstate = DEVSTATE_WRREQUEST;
+
+ /* Update for the next data IN interrupt */
+
+ privreq->req.xfrd += nbytes;
+ bytesleft = privreq->req.len - privreq->req.xfrd;
+
+ /* If all of the bytes were sent (including any final null packet)
+ * then we are finished with the transfer
+ */
+
+ if (bytesleft == 0 && !privep->txnullpkt)
+ {
+ usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
+ privep->txnullpkt = 0;
+ stm32_reqcomplete(privep, OK);
+ priv->devstate = DEVSTATE_IDLE;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_rdrequest
+ ****************************************************************************/
+
+static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
+{
+ struct stm32_req_s *privreq;
+ uint32_t src;
+ uint8_t *dest;
+ uint8_t epno;
+ int pmalen;
+ int readlen;
+
+ /* Check the request from the head of the endpoint request queue */
+
+ epno = USB_EPNO(privep->ep.eplog);
+ privreq = stm32_rqpeek(privep);
+ if (!privreq)
+ {
+ /* Incoming data available in PMA, but no packet to receive the data.
+ * Mark that the RX data is pending and hope that a packet is returned
+ * soon.
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUTQEMPTY), epno);
+ return OK;
+ }
+
+ ullvdbg("EP%d: len=%d xfrd=%d\n", epno, privreq->req.len, privreq->req.xfrd);
+
+ /* Ignore any attempt to receive a zero length packet */
+
+ if (privreq->req.len == 0)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTNULLPACKET), 0);
+ stm32_reqcomplete(privep, OK);
+ return OK;
+ }
+
+ usbtrace(TRACE_READ(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
+
+ /* Get the source and destination transfer addresses */
+
+ dest = privreq->req.buf + privreq->req.xfrd;
+ src = stm32_geteprxaddr(epno);
+
+ /* Get the number of bytes to read from packet memory */
+
+ pmalen = stm32_geteprxcount(epno);
+ readlen = MIN(privreq->req.len, pmalen);
+
+ /* Receive the next packet */
+
+ stm32_copyfrompma(dest, src, readlen);
+ priv->devstate = DEVSTATE_RDREQUEST;
+
+ /* If the receive buffer is full or this is a partial packet,
+ * then we are finished with the transfer
+ */
+
+ privreq->req.xfrd += readlen;
+ if (pmalen < privep->ep.maxpacket || privreq->req.xfrd >= privreq->req.len)
+ {
+ /* Complete the transfer and mark the state IDLE. The endpoint
+ * RX will be marked valid when the data phase completes.
+ */
+
+ usbtrace(TRACE_COMPLETE(epno), privreq->req.xfrd);
+ stm32_reqcomplete(privep, OK);
+ priv->devstate = DEVSTATE_IDLE;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_cancelrequests
+ ****************************************************************************/
+
+static void stm32_cancelrequests(struct stm32_ep_s *privep)
+{
+ while (!stm32_rqempty(privep))
+ {
+ usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)),
+ (stm32_rqpeek(privep))->req.xfrd);
+ stm32_reqcomplete(privep, -ESHUTDOWN);
+ }
+}
+
+/****************************************************************************
+ * Interrupt Level Processing
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_dispatchrequest
+ ****************************************************************************/
+
+static void stm32_dispatchrequest(struct stm32_usbdev_s *priv)
+{
+ int ret;
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DISPATCH), 0);
+ if (priv && priv->driver)
+ {
+ /* Forward to the control request to the class driver implementation */
+
+ ret = CLASS_SETUP(priv->driver, &priv->usbdev, &priv->ctrl, NULL, 0);
+ if (ret < 0)
+ {
+ /* Stall on failure */
+
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DISPATCHSTALL), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_epdone
+ ****************************************************************************/
+
+static void stm32_epdone(struct stm32_usbdev_s *priv, uint8_t epno)
+{
+ struct stm32_ep_s *privep;
+ uint16_t epr;
+
+ /* Decode and service non control endpoints interrupt */
+
+ epr = stm32_getreg(STM32_USB_EPR(epno));
+ privep = &priv->eplist[epno];
+
+ /* OUT: host-to-device
+ * CTR_RX is set by the hardware when an OUT/SETUP transaction
+ * successfully completed on this endpoint.
+ */
+
+ if ((epr & USB_EPR_CTR_RX) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUTDONE), epr);
+
+ /* Handle read requests. First check if a read request is available to
+ * accept the host data.
+ */
+
+ if (!stm32_rqempty(privep))
+ {
+ /* Read host data into the current read request */
+
+ stm32_rdrequest(priv, privep);
+
+ /* "After the received data is processed, the application software
+ * should set the STAT_RX bits to '11' (Valid) in the USB_EPnR,
+ * enabling further transactions. "
+ */
+
+ priv->rxstatus = USB_EPR_STATRX_VALID;
+ }
+
+ /* NAK further OUT packets if there there no more read requests */
+
+ if (stm32_rqempty(privep))
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUTPENDING), (uint16_t)epno);
+
+ /* Mark the RX processing as pending and NAK any OUT actions
+ * on this endpoint. "While the STAT_RX bits are equal to '10'
+ * (NAK), any OUT request addressed to that endpoint is NAKed,
+ * indicating a flow control condition: the USB host will retry
+ * the transaction until it succeeds."
+ */
+
+ priv->rxstatus = USB_EPR_STATRX_NAK;
+ priv->rxpending = true;
+ }
+
+ /* Clear the interrupt status and set the new RX status */
+
+ stm32_clrepctrrx(epno);
+ stm32_seteprxstatus(epno, priv->rxstatus);
+ }
+
+ /* IN: device-to-host
+ * CTR_TX is set when an IN transaction successfully completes on
+ * an endpoint
+ */
+
+ else if ((epr & USB_EPR_CTR_TX) != 0)
+ {
+ /* Clear interrupt status */
+
+ stm32_clrepctrtx(epno);
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPINDONE), epr);
+
+ /* Handle write requests */
+
+ priv->txstatus = USB_EPR_STATTX_NAK;
+ stm32_wrrequest(priv, privep);
+
+ /* Set the new TX status */
+
+ stm32_seteptxstatus(epno, priv->txstatus);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_setdevaddr
+ ****************************************************************************/
+
+static void stm32_setdevaddr(struct stm32_usbdev_s *priv, uint8_t value)
+{
+ int epno;
+
+ /* Set address in every allocated endpoint */
+
+ for (epno = 0; epno < STM32_NENDPOINTS; epno++)
+ {
+ if (stm32_epreserved(priv, epno))
+ {
+ stm32_setepaddress((uint8_t)epno, (uint8_t)epno);
+ }
+ }
+
+ /* Set the device address and enable function */
+
+ stm32_putreg(value|USB_DADDR_EF, STM32_USB_DADDR);
+}
+
+/****************************************************************************
+ * Name: stm32_ep0setup
+ ****************************************************************************/
+
+static void stm32_ep0setup(struct stm32_usbdev_s *priv)
+{
+ struct stm32_ep_s *ep0 = &priv->eplist[EP0];
+ struct stm32_req_s *privreq = stm32_rqpeek(ep0);
+ struct stm32_ep_s *privep;
+ union wb_u value;
+ union wb_u index;
+ union wb_u len;
+ union wb_u response;
+ bool handled = false;
+ uint8_t epno;
+ int nbytes = 0; /* Assume zero-length packet */
+ int ret;
+
+ /* Terminate any pending requests (doesn't work if the pending request
+ * was a zero-length transfer!)
+ */
+
+ while (!stm32_rqempty(ep0))
+ {
+ int16_t result = OK;
+ if (privreq->req.xfrd != privreq->req.len)
+ {
+ result = -EPROTO;
+ }
+
+ usbtrace(TRACE_COMPLETE(ep0->ep.eplog), privreq->req.xfrd);
+ stm32_reqcomplete(ep0, result);
+ }
+
+ /* Assume NOT stalled; no TX in progress */
+
+ ep0->stalled = 0;
+ ep0->txbusy = 0;
+
+ /* Get a 32-bit PMA address and use that to get the 8-byte setup request */
+
+ stm32_copyfrompma((uint8_t*)&priv->ctrl, stm32_geteprxaddr(EP0), USB_SIZEOF_CTRLREQ);
+
+ /* And extract the little-endian 16-bit values to host order */
+
+ value.w = GETUINT16(priv->ctrl.value);
+ index.w = GETUINT16(priv->ctrl.index);
+ len.w = GETUINT16(priv->ctrl.len);
+
+ ullvdbg("SETUP: type=%02x req=%02x value=%04x index=%04x len=%04x\n",
+ priv->ctrl.type, priv->ctrl.req, value.w, index.w, len.w);
+
+ priv->devstate = DEVSTATE_IDLE;
+
+ /* Dispatch any non-standard requests */
+
+ if ((priv->ctrl.type & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_NOSTDREQ), priv->ctrl.type);
+
+ /* Let the class implementation handle all non-standar requests */
+
+ stm32_dispatchrequest(priv);
+ return;
+ }
+
+ /* Handle standard request. Pick off the things of interest to the
+ * USB device controller driver; pass what is left to the class driver
+ */
+
+ switch (priv->ctrl.req)
+ {
+ case USB_REQ_GETSTATUS:
+ {
+ /* type: device-to-host; recipient = device, interface, endpoint
+ * value: 0
+ * index: zero interface endpoint
+ * len: 2; data = status
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSTATUS), priv->ctrl.type);
+ if (len.w != 2 || (priv->ctrl.type & USB_REQ_DIR_IN) == 0 ||
+ index.b[MSB] != 0 || value.w != 0)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPGETSTATUS), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ else
+ {
+ switch (priv->ctrl.type & USB_REQ_RECIPIENT_MASK)
+ {
+ case USB_REQ_RECIPIENT_ENDPOINT:
+ {
+ epno = USB_EPNO(index.b[LSB]);
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPGETSTATUS), epno);
+ if (epno >= STM32_NENDPOINTS)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPGETSTATUS), epno);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ else
+ {
+ privep = &priv->eplist[epno];
+ response.w = 0; /* Not stalled */
+ nbytes = 2; /* Response size: 2 bytes */
+
+ if (USB_ISEPIN(index.b[LSB]))
+ {
+ /* IN endpoint */
+
+ if (stm32_eptxstalled(epno))
+ {
+ /* IN Endpoint stalled */
+
+ response.b[LSB] = 1; /* Stalled */
+ }
+ }
+ else
+ {
+ /* OUT endpoint */
+
+ if (stm32_eprxstalled(epno))
+ {
+ /* OUT Endpoint stalled */
+
+ response.b[LSB] = 1; /* Stalled */
+ }
+ }
+ }
+ }
+ break;
+
+ case USB_REQ_RECIPIENT_DEVICE:
+ {
+ if (index.w == 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_DEVGETSTATUS), 0);
+
+ /* Features: Remote Wakeup=YES; selfpowered=? */
+
+ response.w = 0;
+ response.b[LSB] = (priv->selfpowered << USB_FEATURE_SELFPOWERED) |
+ (1 << USB_FEATURE_REMOTEWAKEUP);
+ nbytes = 2; /* Response size: 2 bytes */
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADDEVGETSTATUS), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ }
+ break;
+
+ case USB_REQ_RECIPIENT_INTERFACE:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_IFGETSTATUS), 0);
+ response.w = 0;
+ nbytes = 2; /* Response size: 2 bytes */
+ }
+ break;
+
+ default:
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSTATUS), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ case USB_REQ_CLEARFEATURE:
+ {
+ /* type: host-to-device; recipient = device, interface or endpoint
+ * value: feature selector
+ * index: zero interface endpoint;
+ * len: zero, data = none
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_CLEARFEATURE), priv->ctrl.type);
+ if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_ENDPOINT)
+ {
+ /* Let the class implementation handle all recipients (except for the
+ * endpoint recipient)
+ */
+
+ stm32_dispatchrequest(priv);
+ handled = true;
+ }
+ else
+ {
+ /* Endpoint recipient */
+
+ epno = USB_EPNO(index.b[LSB]);
+ if (epno < STM32_NENDPOINTS && index.b[MSB] == 0 &&
+ value.w == USB_FEATURE_ENDPOINTHALT && len.w == 0)
+ {
+ privep = &priv->eplist[epno];
+ privep->halted = 0;
+ ret = stm32_epstall(&privep->ep, true);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADCLEARFEATURE), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ }
+ }
+ break;
+
+ case USB_REQ_SETFEATURE:
+ {
+ /* type: host-to-device; recipient = device, interface, endpoint
+ * value: feature selector
+ * index: zero interface endpoint;
+ * len: 0; data = none
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETFEATURE), priv->ctrl.type);
+ if (((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) &&
+ value.w == USB_FEATURE_TESTMODE)
+ {
+ /* Special case recipient=device test mode */
+
+ ullvdbg("test mode: %d\n", index.w);
+ }
+ else if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_ENDPOINT)
+ {
+ /* The class driver handles all recipients except recipient=endpoint */
+
+ stm32_dispatchrequest(priv);
+ handled = true;
+ }
+ else
+ {
+ /* Handler recipient=endpoint */
+
+ epno = USB_EPNO(index.b[LSB]);
+ if (epno < STM32_NENDPOINTS && index.b[MSB] == 0 &&
+ value.w == USB_FEATURE_ENDPOINTHALT && len.w == 0)
+ {
+ privep = &priv->eplist[epno];
+ privep->halted = 1;
+ ret = stm32_epstall(&privep->ep, false);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETFEATURE), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ }
+ }
+ break;
+
+ case USB_REQ_SETADDRESS:
+ {
+ /* type: host-to-device; recipient = device
+ * value: device address
+ * index: 0
+ * len: 0; data = none
+ */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0SETUPSETADDRESS), value.w);
+ if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_DEVICE ||
+ index.w != 0 || len.w != 0 || value.w > 127)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETADDRESS), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+
+ /* Note that setting of the device address will be deferred. A zero-length
+ * packet will be sent and the device address will be set when the zero-
+ * length packet transfer completes.
+ */
+ }
+ break;
+
+ case USB_REQ_GETDESCRIPTOR:
+ /* type: device-to-host; recipient = device
+ * value: descriptor type and index
+ * index: 0 or language ID;
+ * len: descriptor len; data = descriptor
+ */
+ case USB_REQ_SETDESCRIPTOR:
+ /* type: host-to-device; recipient = device
+ * value: descriptor type and index
+ * index: 0 or language ID;
+ * len: descriptor len; data = descriptor
+ */
+
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSETDESC), priv->ctrl.type);
+ if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE)
+ {
+ /* The request seems valid... let the class implementation handle it */
+
+ stm32_dispatchrequest(priv);
+ handled = true;
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSETDESC), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ }
+ break;
+
+ case USB_REQ_GETCONFIGURATION:
+ /* type: device-to-host; recipient = device
+ * value: 0;
+ * index: 0;
+ * len: 1; data = configuration value
+ */
+
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETCONFIG), priv->ctrl.type);
+ if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
+ value.w == 0 && index.w == 0 && len.w == 1)
+ {
+ /* The request seems valid... let the class implementation handle it */
+
+ stm32_dispatchrequest(priv);
+ handled = true;
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETCONFIG), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ }
+ break;
+
+ case USB_REQ_SETCONFIGURATION:
+ /* type: host-to-device; recipient = device
+ * value: configuration value
+ * index: 0;
+ * len: 0; data = none
+ */
+
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETCONFIG), priv->ctrl.type);
+ if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
+ index.w == 0 && len.w == 0)
+ {
+ /* The request seems valid... let the class implementation handle it */
+
+ stm32_dispatchrequest(priv);
+ handled = true;
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETCONFIG), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ }
+ break;
+
+ case USB_REQ_GETINTERFACE:
+ /* type: device-to-host; recipient = interface
+ * value: 0
+ * index: interface;
+ * len: 1; data = alt interface
+ */
+ case USB_REQ_SETINTERFACE:
+ /* type: host-to-device; recipient = interface
+ * value: alternate setting
+ * index: interface;
+ * len: 0; data = none
+ */
+
+ {
+ /* Let the class implementation handle the request */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_GETSETIF), priv->ctrl.type);
+ stm32_dispatchrequest(priv);
+ handled = true;
+ }
+ break;
+
+ case USB_REQ_SYNCHFRAME:
+ /* type: device-to-host; recipient = endpoint
+ * value: 0
+ * index: endpoint;
+ * len: 2; data = frame number
+ */
+
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SYNCHFRAME), 0);
+ }
+ break;
+
+ default:
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDCTRLREQ), priv->ctrl.req);
+ priv->devstate = DEVSTATE_STALLED;
+ }
+ break;
+ }
+
+ /* At this point, the request has been handled and there are three possible
+ * outcomes:
+ *
+ * 1. The setup request was successfully handled above and a response packet
+ * must be sent (may be a zero length packet).
+ * 2. The request was successfully handled by the class implementation. In
+ * case, the EP0 IN response has already been queued and the local variable
+ * 'handled' will be set to true and devstate != DEVSTATE_STALLED;
+ * 3. An error was detected in either the above logic or by the class implementation
+ * logic. In either case, priv->state will be set DEVSTATE_STALLED
+ * to indicate this case.
+ *
+ * NOTE: Non-standard requests are a special case. They are handled by the
+ * class implementation and this function returned early above, skipping this
+ * logic altogether.
+ */
+
+ if (priv->devstate != DEVSTATE_STALLED && !handled)
+ {
+ /* We will response. First, restrict the data length to the length
+ * requested in the setup packet
+ */
+
+ if (nbytes > len.w)
+ {
+ nbytes = len.w;
+ }
+
+ /* Send the response (might be a zero-length packet) */
+
+ stm32_epwrite(priv, ep0, response.b, nbytes);
+ priv->devstate = DEVSTATE_IDLE;
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_ep0in
+ ****************************************************************************/
+
+static void stm32_ep0in(struct stm32_usbdev_s *priv)
+{
+ /* There is no longer anything in the EP0 TX packet memory */
+
+ priv->eplist[EP0].txbusy = false;
+
+ /* Are we processing the completion of one packet of an outgoing request
+ * from the class driver?
+ */
+
+ if (priv->devstate == DEVSTATE_WRREQUEST)
+ {
+ stm32_wrrequest(priv, &priv->eplist[EP0]);
+ }
+
+ /* No.. Are we processing the completion of a status response? */
+
+ else if (priv->devstate == DEVSTATE_IDLE)
+ {
+ /* Look at the saved SETUP command. Was it a SET ADDRESS request?
+ * If so, then now is the time to set the address.
+ */
+
+ if (priv->ctrl.req == USB_REQ_SETADDRESS &&
+ (priv->ctrl.type & REQRECIPIENT_MASK) == (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_DEVICE))
+ {
+ union wb_u value;
+ value.w = GETUINT16(priv->ctrl.value);
+ stm32_setdevaddr(priv, value.b[LSB]);
+ }
+ }
+ else
+ {
+ priv->devstate = DEVSTATE_STALLED;
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_ep0out
+ ****************************************************************************/
+
+static void stm32_ep0out(struct stm32_usbdev_s *priv)
+{
+ struct stm32_ep_s *privep = &priv->eplist[EP0];
+ switch (priv->devstate)
+ {
+ case DEVSTATE_RDREQUEST: /* Write request in progress */
+ case DEVSTATE_IDLE: /* No transfer in progress */
+ stm32_rdrequest(priv, privep);
+ break;
+
+ default:
+ /* Unexpected state OR host aborted the OUT transfer before it
+ * completed, STALL the endpoint in either case
+ */
+
+ priv->devstate = DEVSTATE_STALLED;
+ break;
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_ep0done
+ ****************************************************************************/
+
+static inline void stm32_ep0done(struct stm32_usbdev_s *priv, uint16_t istr)
+{
+ uint16_t epr;
+
+ /* Initialize RX and TX status. We shouldn't have to actually look at the
+ * status because the hardware is supposed to set the both RX and TX status
+ * to NAK when an EP0 SETUP occurs (of course, this might not be a setup)
+ */
+
+ priv->rxstatus = USB_EPR_STATRX_NAK;
+ priv->txstatus = USB_EPR_STATTX_NAK;
+
+ /* Set both RX and TX status to NAK */
+
+ stm32_seteprxstatus(EP0, USB_EPR_STATRX_NAK);
+ stm32_seteptxstatus(EP0, USB_EPR_STATTX_NAK);
+
+ /* Check the direction bit to determine if this the completion of an EP0
+ * packet sent to or received from the host PC.
+ */
+
+ if ((istr & USB_ISTR_DIR) == 0)
+ {
+ /* EP0 IN: device-to-host (DIR=0) */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0IN), istr);
+ stm32_clrepctrtx(EP0);
+ stm32_ep0in(priv);
+ }
+ else
+ {
+ /* EP0 OUT: host-to-device (DIR=1) */
+
+ epr = stm32_getreg(STM32_USB_EPR(EP0));
+
+ /* CTR_TX is set when an IN transaction successfully
+ * completes on an endpoint
+ */
+
+ if ((epr & USB_EPR_CTR_TX) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0INDONE), epr);
+ stm32_clrepctrtx(EP0);
+ stm32_ep0in(priv);
+ }
+
+ /* SETUP is set by the hardware when the last completed
+ * transaction was a control endpoint SETUP
+ */
+
+ else if ((epr & USB_EPR_SETUP) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0SETUPDONE), epr);
+ stm32_clrepctrrx(EP0);
+ stm32_ep0setup(priv);
+ }
+
+ /* Set by the hardware when an OUT/SETUP transaction successfully
+ * completed on this endpoint.
+ */
+
+ else if ((epr & USB_EPR_CTR_RX) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EP0OUTDONE), epr);
+ stm32_clrepctrrx(EP0);
+ stm32_ep0out(priv);
+ }
+
+ /* None of the above */
+
+ else
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0BADCTR), epr);
+ return; /* Does this ever happen? */
+ }
+ }
+
+ /* Make sure that the EP0 packet size is still OK (superstitious?) */
+
+ stm32_seteprxcount(EP0, STM32_EP0MAXPACKET);
+
+ /* Now figure out the new RX/TX status. Here are all possible
+ * consequences of the above EP0 operations:
+ *
+ * rxstatus txstatus devstate MEANING
+ * -------- -------- --------- ---------------------------------
+ * NAK NAK IDLE Nothing happened
+ * NAK VALID IDLE EP0 response sent from USBDEV driver
+ * NAK VALID WRREQUEST EP0 response sent from class driver
+ * NAK --- STALL Some protocol error occurred
+ *
+ * First handle the STALL condition:
+ */
+
+ if (priv->devstate == DEVSTATE_STALLED)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->devstate);
+ priv->rxstatus = USB_EPR_STATRX_STALL;
+ priv->txstatus = USB_EPR_STATTX_STALL;
+ }
+
+ /* Was a transmission started? If so, txstatus will be VALID. The
+ * only special case to handle is when both are set to NAK. In that
+ * case, we need to set RX status to VALID in order to accept the next
+ * SETUP request.
+ */
+
+ else if (priv->rxstatus == USB_EPR_STATRX_NAK &&
+ priv->txstatus == USB_EPR_STATTX_NAK)
+ {
+ priv->rxstatus = USB_EPR_STATRX_VALID;
+ }
+
+ /* Now set the new TX and RX status */
+
+ stm32_seteprxstatus(EP0, priv->rxstatus);
+ stm32_seteptxstatus(EP0, priv->txstatus);
+}
+
+/****************************************************************************
+ * Name: stm32_lptransfer
+ ****************************************************************************/
+
+static void stm32_lptransfer(struct stm32_usbdev_s *priv)
+{
+ uint8_t epno;
+ uint16_t istr;
+
+ /* Stay in loop while LP interrupts are pending */
+
+ while (((istr = stm32_getreg(STM32_USB_ISTR)) & USB_ISTR_CTR) != 0)
+ {
+ stm32_putreg((uint16_t)~USB_ISTR_CTR, STM32_USB_ISTR);
+
+ /* Extract highest priority endpoint number */
+
+ epno = (uint8_t)(istr & USB_ISTR_EPID_MASK);
+
+ /* Handle EP0 completion events */
+
+ if (epno == 0)
+ {
+ stm32_ep0done(priv, istr);
+ }
+
+ /* Handle other endpoint completion events */
+
+ else
+ {
+ stm32_epdone(priv, epno);
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_hpinterrupt
+ ****************************************************************************/
+
+static int stm32_hpinterrupt(int irq, void *context)
+{
+ /* For now there is only one USB controller, but we will always refer to
+ * it using a pointer to make any future ports to multiple USB controllers
+ * easier.
+ */
+
+ struct stm32_usbdev_s *priv = &g_usbdev;
+ uint16_t istr;
+ uint8_t epno;
+
+ /* High priority interrupts are only triggered by a correct transfer event
+ * for isochronous and double-buffer bulk transfers.
+ */
+
+ istr = stm32_getreg(STM32_USB_ISTR);
+ usbtrace(TRACE_INTENTRY(STM32_TRACEINTID_HPINTERRUPT), istr);
+ while ((istr & USB_ISTR_CTR) != 0)
+ {
+ stm32_putreg((uint16_t)~USB_ISTR_CTR, STM32_USB_ISTR);
+
+ /* Extract highest priority endpoint number */
+
+ epno = (uint8_t)(istr & USB_ISTR_EPID_MASK);
+
+ /* And handle the completion event */
+
+ stm32_epdone(priv, epno);
+
+ /* Fetch the status again for the next time through the loop */
+
+ istr = stm32_getreg(STM32_USB_ISTR);
+ }
+
+ usbtrace(TRACE_INTEXIT(STM32_TRACEINTID_HPINTERRUPT), 0);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_lpinterrupt
+ ****************************************************************************/
+
+static int stm32_lpinterrupt(int irq, void *context)
+{
+ /* For now there is only one USB controller, but we will always refer to
+ * it using a pointer to make any future ports to multiple USB controllers
+ * easier.
+ */
+
+ struct stm32_usbdev_s *priv = &g_usbdev;
+ uint16_t istr = stm32_getreg(STM32_USB_ISTR);
+
+ usbtrace(TRACE_INTENTRY(STM32_TRACEINTID_LPINTERRUPT), istr);
+
+ /* Handle Reset interrupts. When this event occurs, the peripheral is left
+ * in the same conditions it is left by the system reset (but with the
+ * USB controller enabled).
+ */
+
+ if ((istr & USB_ISTR_RESET) != 0)
+ {
+ /* Reset interrupt received. Clear the RESET interrupt status. */
+
+ stm32_putreg(~USB_ISTR_RESET, STM32_USB_ISTR);
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_RESET), istr);
+
+ /* Restore our power-up state and exit now because istr is no longer
+ * valid.
+ */
+
+ stm32_reset(priv);
+ goto exit_lpinterrupt;
+ }
+
+ /* Handle Wakeup interrupts. This interrupt is only enable while the USB is
+ * suspended.
+ */
+
+ if ((istr & USB_ISTR_WKUP & priv->imask) != 0)
+ {
+ /* Wakeup interrupt received. Clear the WKUP interrupt status. The
+ * cause of the resume is indicated in the FNR register
+ */
+
+ stm32_putreg(~USB_ISTR_WKUP, STM32_USB_ISTR);
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_WKUP), stm32_getreg(STM32_USB_FNR));
+
+ /* Perform the wakeup action */
+
+ stm32_initresume(priv);
+ priv->rsmstate = RSMSTATE_IDLE;
+
+ /* Disable ESOF polling, disable the wakeup interrupt, and
+ * re-enable the suspend interrupt. Clear any pending SUSP
+ * interrupts.
+ */
+
+ stm32_setimask(priv, USB_CNTR_SUSPM, USB_CNTR_ESOFM|USB_CNTR_WKUPM);
+ stm32_putreg(~USB_CNTR_SUSPM, STM32_USB_ISTR);
+ }
+
+ if ((istr & USB_ISTR_SUSP & priv->imask) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SUSP), 0);
+ stm32_suspend(priv);
+
+ /* Clear of the ISTR bit must be done after setting of USB_CNTR_FSUSP */
+
+ stm32_putreg(~USB_ISTR_SUSP, STM32_USB_ISTR);
+ }
+
+ if ((istr & USB_ISTR_ESOF & priv->imask) != 0)
+ {
+ stm32_putreg(~USB_ISTR_ESOF, STM32_USB_ISTR);
+
+ /* Resume handling timing is made with ESOFs */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_ESOF), 0);
+ stm32_esofpoll(priv);
+ }
+
+ if ((istr & USB_ISTR_CTR & priv->imask) != 0)
+ {
+ /* Low priority endpoint correct transfer interrupt */
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_LPCTR), istr);
+ stm32_lptransfer(priv);
+ }
+
+exit_lpinterrupt:
+ usbtrace(TRACE_INTEXIT(STM32_TRACEINTID_LPINTERRUPT), stm32_getreg(STM32_USB_EP0R));
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_setimask
+ ****************************************************************************/
+
+static void
+stm32_setimask(struct stm32_usbdev_s *priv, uint16_t setbits, uint16_t clrbits)
+{
+ uint16_t regval;
+
+ /* Adjust the interrupt mask bits in the shadow copy first */
+
+ priv->imask &= ~clrbits;
+ priv->imask |= setbits;
+
+ /* Then make the interrupt mask bits in the CNTR register match the shadow
+ * register (Hmmm... who is shadowing whom?)
+ */
+
+ regval = stm32_getreg(STM32_USB_CNTR);
+ regval &= ~USB_CNTR_ALLINTS;
+ regval |= priv->imask;
+ stm32_putreg(regval, STM32_USB_CNTR);
+}
+
+/****************************************************************************
+ * Suspend/Resume Helpers
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_suspend
+ ****************************************************************************/
+
+static void stm32_suspend(struct stm32_usbdev_s *priv)
+{
+ uint16_t regval;
+
+ /* Disable ESOF polling, disable the SUSP interrupt, and enable the WKUP
+ * interrupt. Clear any pending WKUP interrupt.
+ */
+
+ stm32_setimask(priv, USB_CNTR_WKUPM, USB_CNTR_ESOFM|USB_CNTR_SUSPM);
+ stm32_putreg(~USB_ISTR_WKUP, STM32_USB_ISTR);
+
+ /* Set the FSUSP bit in the CNTR register. This activates suspend mode
+ * within the USB peripheral and disables further SUSP interrupts.
+ */
+
+ regval = stm32_getreg(STM32_USB_CNTR);
+ regval |= USB_CNTR_FSUSP;
+ stm32_putreg(regval, STM32_USB_CNTR);
+
+ /* If we are not a self-powered device, the got to low-power mode */
+
+ if (!priv->selfpowered)
+ {
+ /* Setting LPMODE in the CNTR register removes static power
+ * consumption in the USB analog transceivers but keeps them
+ * able to detect resume activity
+ */
+
+ regval = stm32_getreg(STM32_USB_CNTR);
+ regval |= USB_CNTR_LPMODE;
+ stm32_putreg(regval, STM32_USB_CNTR);
+ }
+
+ /* Let the board-specific logic know that we have entered the suspend
+ * state
+ */
+
+ stm32_usbsuspend((struct usbdev_s *)priv, false);
+}
+
+/****************************************************************************
+ * Name: stm32_initresume
+ ****************************************************************************/
+
+static void stm32_initresume(struct stm32_usbdev_s *priv)
+{
+ uint16_t regval;
+
+ /* This function is called when either (1) a WKUP interrupt is received from
+ * the host PC, or (2) the class device implementation calls the wakeup()
+ * method.
+ */
+
+ /* Clear the USB low power mode (lower power mode was not set if this is
+ * a self-powered device. Also, low power mode is automatically cleared by
+ * hardware when a WKUP interrupt event occurs).
+ */
+
+ regval = stm32_getreg(STM32_USB_CNTR);
+ regval &= (~USB_CNTR_LPMODE);
+ stm32_putreg(regval, STM32_USB_CNTR);
+
+ /* Restore full power -- whatever that means for this particular board */
+
+ stm32_usbsuspend((struct usbdev_s *)priv, true);
+
+ /* Reset FSUSP bit and enable normal interrupt handling */
+
+ stm32_putreg(STM32_CNTR_SETUP, STM32_USB_CNTR);
+}
+
+/****************************************************************************
+ * Name: stm32_esofpoll
+ ****************************************************************************/
+
+static void stm32_esofpoll(struct stm32_usbdev_s *priv)
+{
+ uint16_t regval;
+
+ /* Called periodically from ESOF interrupt after RSMSTATE_STARTED */
+
+ switch (priv->rsmstate)
+ {
+ /* One ESOF after internal resume requested */
+
+ case RSMSTATE_STARTED:
+ regval = stm32_getreg(STM32_USB_CNTR);
+ regval |= USB_CNTR_RESUME;
+ stm32_putreg(regval, STM32_USB_CNTR);
+ priv->rsmstate = RSMSTATE_WAITING;
+ priv->nesofs = 10;
+ break;
+
+ /* Countdown before completing the operation */
+
+ case RSMSTATE_WAITING:
+ priv->nesofs--;
+ if (priv->nesofs == 0)
+ {
+ /* Okay.. we are ready to resume normal operation */
+
+ regval = stm32_getreg(STM32_USB_CNTR);
+ regval &= (~USB_CNTR_RESUME);
+ stm32_putreg(regval, STM32_USB_CNTR);
+ priv->rsmstate = RSMSTATE_IDLE;
+
+ /* Disable ESOF polling, disable the SUSP interrupt, and enable
+ * the WKUP interrupt. Clear any pending WKUP interrupt.
+ */
+
+ stm32_setimask(priv, USB_CNTR_WKUPM, USB_CNTR_ESOFM|USB_CNTR_SUSPM);
+ stm32_putreg(~USB_ISTR_WKUP, STM32_USB_ISTR);
+ }
+ break;
+
+ case RSMSTATE_IDLE:
+ default:
+ priv->rsmstate = RSMSTATE_IDLE;
+ break;
+ }
+}
+
+/****************************************************************************
+ * Endpoint Helpers
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_epreserve
+ ****************************************************************************/
+
+static inline struct stm32_ep_s *
+stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset)
+{
+ struct stm32_ep_s *privep = NULL;
+ irqstate_t flags;
+ int epndx = 0;
+
+ flags = irqsave();
+ epset &= priv->epavail;
+ if (epset)
+ {
+ /* Select the lowest bit in the set of matching, available endpoints
+ * (skipping EP0)
+ */
+
+ for (epndx = 1; epndx < STM32_NENDPOINTS; epndx++)
+ {
+ uint8_t bit = STM32_ENDP_BIT(epndx);
+ if ((epset & bit) != 0)
+ {
+ /* Mark the endpoint no longer available */
+
+ priv->epavail &= ~bit;
+
+ /* And return the pointer to the standard endpoint structure */
+
+ privep = &priv->eplist[epndx];
+ break;
+ }
+ }
+ }
+
+ irqrestore(flags);
+ return privep;
+}
+
+/****************************************************************************
+ * Name: stm32_epunreserve
+ ****************************************************************************/
+
+static inline void
+stm32_epunreserve(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
+{
+ irqstate_t flags = irqsave();
+ priv->epavail |= STM32_ENDP_BIT(USB_EPNO(privep->ep.eplog));
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: stm32_epreserved
+ ****************************************************************************/
+
+static inline bool
+stm32_epreserved(struct stm32_usbdev_s *priv, int epno)
+{
+ return ((priv->epavail & STM32_ENDP_BIT(epno)) == 0);
+}
+
+/****************************************************************************
+ * Name: stm32_epallocpma
+ ****************************************************************************/
+
+static int stm32_epallocpma(struct stm32_usbdev_s *priv)
+{
+ irqstate_t flags;
+ int bufno = ERROR;
+ int bufndx;
+
+ flags = irqsave();
+ for (bufndx = 2; bufndx < STM32_NBUFFERS; bufndx++)
+ {
+ /* Check if this buffer is available */
+
+ uint8_t bit = STM32_BUFFER_BIT(bufndx);
+ if ((priv->bufavail & bit) != 0)
+ {
+ /* Yes.. Mark the endpoint no longer available */
+
+ priv->bufavail &= ~bit;
+
+ /* And return the index of the allocated buffer */
+
+ bufno = bufndx;
+ break;
+ }
+ }
+
+ irqrestore(flags);
+ return bufno;
+}
+
+/****************************************************************************
+ * Name: stm32_epfreepma
+ ****************************************************************************/
+
+static inline void
+stm32_epfreepma(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
+{
+ irqstate_t flags = irqsave();
+ priv->epavail |= STM32_ENDP_BIT(privep->bufno);
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Endpoint operations
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_epconfigure
+ ****************************************************************************/
+
+static int stm32_epconfigure(struct usbdev_ep_s *ep,
+ const struct usb_epdesc_s *desc,
+ bool last)
+{
+ struct stm32_ep_s *privep = (struct stm32_ep_s *)ep;
+ uint16_t pma;
+ uint16_t setting;
+ uint16_t maxpacket;
+ uint8_t epno;
+
+#ifdef CONFIG_DEBUG
+ if (!ep || !desc)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ ulldbg("ERROR: ep=%p desc=%p\n");
+ return -EINVAL;
+ }
+#endif
+
+ /* Get the unadorned endpoint address */
+
+ epno = USB_EPNO(desc->addr);
+ usbtrace(TRACE_EPCONFIGURE, (uint16_t)epno);
+ DEBUGASSERT(epno == USB_EPNO(ep->eplog));
+
+ /* Set the requested type */
+
+ switch (desc->attr & USB_EP_ATTR_XFERTYPE_MASK)
+ {
+ case USB_EP_ATTR_XFER_INT: /* Interrupt endpoint */
+ setting = USB_EPR_EPTYPE_INTERRUPT;
+ break;
+
+ case USB_EP_ATTR_XFER_BULK: /* Bulk endpoint */
+ setting = USB_EPR_EPTYPE_BULK;
+ break;
+
+ case USB_EP_ATTR_XFER_ISOC: /* Isochronous endpoint */
+#warning "REVISIT: Need to review isochronous EP setup"
+ setting = USB_EPR_EPTYPE_ISOC;
+ break;
+
+ case USB_EP_ATTR_XFER_CONTROL: /* Control endpoint */
+ setting = USB_EPR_EPTYPE_CONTROL;
+ break;
+
+ default:
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPTYPE), (uint16_t)desc->type);
+ return -EINVAL;
+ }
+
+ stm32_seteptype(epno, setting);
+
+ /* Get the address of the PMA buffer allocated for this endpoint */
+
+#warning "REVISIT: Should configure BULK EPs using double buffer feature"
+ pma = STM32_BUFNO2BUF(privep->bufno);
+
+ /* Get the maxpacket size of the endpoint. */
+
+ maxpacket = GETUINT16(desc->mxpacketsize);
+ DEBUGASSERT(maxpacket <= STM32_MAXPACKET_SIZE);
+ ep->maxpacket = maxpacket;
+
+ /* Get the subset matching the requested direction */
+
+ if (USB_ISEPIN(desc->addr))
+ {
+ /* The full, logical EP number includes direction */
+
+ ep->eplog = USB_EPIN(epno);
+
+ /* Set up TX; disable RX */
+
+ stm32_seteptxaddr(epno, pma);
+ stm32_seteptxstatus(epno, USB_EPR_STATTX_NAK);
+ stm32_seteprxstatus(epno, USB_EPR_STATRX_DIS);
+ }
+ else
+ {
+ /* The full, logical EP number includes direction */
+
+ ep->eplog = USB_EPOUT(epno);
+
+ /* Set up RX; disable TX */
+
+ stm32_seteprxaddr(epno, pma);
+ stm32_seteprxcount(epno, maxpacket);
+ stm32_seteprxstatus(epno, USB_EPR_STATRX_VALID);
+ stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS);
+ }
+
+ stm32_dumpep(epno);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_epdisable
+ ****************************************************************************/
+
+static int stm32_epdisable(struct usbdev_ep_s *ep)
+{
+ struct stm32_ep_s *privep = (struct stm32_ep_s *)ep;
+ irqstate_t flags;
+ uint8_t epno;
+
+#ifdef CONFIG_DEBUG
+ if (!ep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ ulldbg("ERROR: ep=%p\n", ep);
+ return -EINVAL;
+ }
+#endif
+
+ epno = USB_EPNO(ep->eplog);
+ usbtrace(TRACE_EPDISABLE, epno);
+
+ /* Cancel any ongoing activity */
+
+ flags = irqsave();
+ stm32_cancelrequests(privep);
+
+ /* Disable TX; disable RX */
+
+ stm32_seteprxcount(epno, 0);
+ stm32_seteprxstatus(epno, USB_EPR_STATRX_DIS);
+ stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS);
+
+ irqrestore(flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_epallocreq
+ ****************************************************************************/
+
+static struct usbdev_req_s *stm32_epallocreq(struct usbdev_ep_s *ep)
+{
+ struct stm32_req_s *privreq;
+
+#ifdef CONFIG_DEBUG
+ if (!ep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return NULL;
+ }
+#endif
+ usbtrace(TRACE_EPALLOCREQ, USB_EPNO(ep->eplog));
+
+ privreq = (struct stm32_req_s *)malloc(sizeof(struct stm32_req_s));
+ if (!privreq)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_ALLOCFAIL), 0);
+ return NULL;
+ }
+
+ memset(privreq, 0, sizeof(struct stm32_req_s));
+ return &privreq->req;
+}
+
+/****************************************************************************
+ * Name: stm32_epfreereq
+ ****************************************************************************/
+
+static void stm32_epfreereq(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
+{
+ struct stm32_req_s *privreq = (struct stm32_req_s*)req;
+
+#ifdef CONFIG_DEBUG
+ if (!ep || !req)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return;
+ }
+#endif
+ usbtrace(TRACE_EPFREEREQ, USB_EPNO(ep->eplog));
+
+ free(privreq);
+}
+
+/****************************************************************************
+ * Name: stm32_epsubmit
+ ****************************************************************************/
+
+static int stm32_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
+{
+ struct stm32_req_s *privreq = (struct stm32_req_s *)req;
+ struct stm32_ep_s *privep = (struct stm32_ep_s *)ep;
+ struct stm32_usbdev_s *priv;
+ irqstate_t flags;
+ uint8_t epno;
+ int ret = OK;
+
+#ifdef CONFIG_DEBUG
+ if (!req || !req->callback || !req->buf || !ep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ ulldbg("ERROR: req=%p callback=%p buf=%p ep=%p\n", req, req->callback, req->buf, ep);
+ return -EINVAL;
+ }
+#endif
+
+ usbtrace(TRACE_EPSUBMIT, USB_EPNO(ep->eplog));
+ priv = privep->dev;
+
+#ifdef CONFIG_DEBUG
+ if (!priv->driver)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_NOTCONFIGURED), priv->usbdev.speed);
+ ulldbg("ERROR: driver=%p\n", priv->driver);
+ return -ESHUTDOWN;
+ }
+#endif
+
+ /* Handle the request from the class driver */
+
+ epno = USB_EPNO(ep->eplog);
+ req->result = -EINPROGRESS;
+ req->xfrd = 0;
+ flags = irqsave();
+
+ /* If we are stalled, then drop all requests on the floor */
+
+ if (privep->stalled)
+ {
+ stm32_abortrequest(privep, privreq, -EBUSY);
+ ulldbg("ERROR: stalled\n");
+ ret = -EBUSY;
+ }
+
+ /* Handle IN (device-to-host) requests. NOTE: If the class device is
+ * using the bi-directional EP0, then we assume that they intend the EP0
+ * IN functionality.
+ */
+
+ else if (USB_ISEPIN(ep->eplog) || epno == EP0)
+ {
+ /* Add the new request to the request queue for the IN endpoint */
+
+ stm32_rqenqueue(privep, privreq);
+ usbtrace(TRACE_INREQQUEUED(epno), req->len);
+
+ /* If the IN endpoint FIFO is available, then transfer the data now */
+
+ if (!privep->txbusy)
+ {
+ priv->txstatus = USB_EPR_STATTX_NAK;
+ ret = stm32_wrrequest(priv, privep);
+
+ /* Set the new TX status */
+
+ stm32_seteptxstatus(epno, priv->txstatus);
+ }
+ }
+
+ /* Handle OUT (host-to-device) requests */
+
+ else
+ {
+ /* Add the new request to the request queue for the OUT endpoint */
+
+ privep->txnullpkt = 0;
+ stm32_rqenqueue(privep, privreq);
+ usbtrace(TRACE_OUTREQQUEUED(epno), req->len);
+
+ /* This there a incoming data pending the availability of a request? */
+
+ if (priv->rxpending)
+ {
+ /* Set STAT_RX bits to '11' in the USB_EPnR, enabling further
+ * transactions. "While the STAT_RX bits are equal to '10'
+ * (NAK), any OUT request addressed to that endpoint is NAKed,
+ * indicating a flow control condition: the USB host will retry
+ * the transaction until it succeeds."
+ */
+
+ priv->rxstatus = USB_EPR_STATRX_VALID;
+ stm32_seteprxstatus(epno, priv->rxstatus);
+
+ /* Data is no longer pending */
+
+ priv->rxpending = false;
+ }
+ }
+
+ irqrestore(flags);
+ return ret;
+}
+
+/****************************************************************************
+ * Name: stm32_epcancel
+ ****************************************************************************/
+
+static int stm32_epcancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
+{
+ struct stm32_ep_s *privep = (struct stm32_ep_s *)ep;
+ struct stm32_usbdev_s *priv;
+ irqstate_t flags;
+
+#ifdef CONFIG_DEBUG
+ if (!ep || !req)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+ usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog));
+ priv = privep->dev;
+
+ flags = irqsave();
+ stm32_cancelrequests(privep);
+ irqrestore(flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_epstall
+ ****************************************************************************/
+
+static int stm32_epstall(struct usbdev_ep_s *ep, bool resume)
+{
+ struct stm32_ep_s *privep;
+ struct stm32_usbdev_s *priv;
+ uint8_t epno = USB_EPNO(ep->eplog);
+ uint16_t status;
+ irqstate_t flags;
+
+#ifdef CONFIG_DEBUG
+ if (!ep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+ privep = (struct stm32_ep_s *)ep;
+ priv = (struct stm32_usbdev_s *)privep->dev;
+ epno = USB_EPNO(ep->eplog);
+
+ /* STALL or RESUME the endpoint */
+
+ flags = irqsave();
+ usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, USB_EPNO(ep->eplog));
+
+ /* Get status of the endpoint; stall the request if the endpoint is
+ * disabled
+ */
+
+ if (USB_ISEPIN(ep->eplog))
+ {
+ status = stm32_geteptxstatus(epno);
+ }
+ else
+ {
+ status = stm32_geteprxstatus(epno);
+ }
+
+ if (status == 0)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPDISABLED), 0);
+ priv->devstate = DEVSTATE_STALLED;
+ return -ENODEV;
+ }
+
+ /* Handle the resume condition */
+
+ if (resume)
+ {
+ /* Resuming a stalled endpoint */
+
+ usbtrace(TRACE_EPRESUME, epno);
+ privep->stalled = false;
+
+ if (USB_ISEPIN(ep->eplog))
+ {
+ /* IN endpoint */
+
+ if (stm32_eptxstalled(epno))
+ {
+ stm32_clrtxdtog(epno);
+
+ /* Restart any queued write requests */
+
+ priv->txstatus = USB_EPR_STATTX_NAK;
+ (void)stm32_wrrequest(priv, privep);
+
+ /* Set the new TX status */
+
+ stm32_seteptxstatus(epno, priv->txstatus);
+ }
+ }
+ else
+ {
+ /* OUT endpoint */
+
+ if (stm32_eprxstalled(epno))
+ {
+ if (epno == EP0)
+ {
+ /* After clear the STALL, enable the default endpoint receiver */
+
+ stm32_seteprxcount(epno, ep->maxpacket);
+ }
+ else
+ {
+ stm32_clrrxdtog(epno);
+ }
+
+ priv->rxstatus = USB_EPR_STATRX_VALID;
+ stm32_seteprxstatus(epno, USB_EPR_STATRX_VALID);
+ }
+ }
+ }
+
+ /* Handle the stall condition */
+
+ else
+ {
+ usbtrace(TRACE_EPSTALL, epno);
+ privep->stalled = true;
+
+ if (USB_ISEPIN(ep->eplog))
+ {
+ /* IN endpoint */
+
+ priv->txstatus = USB_EPR_STATTX_STALL;
+ stm32_seteptxstatus(epno, USB_EPR_STATTX_STALL);
+ }
+ else
+ {
+ /* OUT endpoint */
+
+ priv->rxstatus = USB_EPR_STATRX_STALL;
+ stm32_seteprxstatus(epno, USB_EPR_STATRX_STALL);
+ }
+ }
+
+ irqrestore(flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Device Controller Operations
+ ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_allocep
+ ****************************************************************************/
+
+static struct usbdev_ep_s *stm32_allocep(struct usbdev_s *dev, uint8_t epno,
+ bool in, uint8_t eptype)
+{
+ struct stm32_usbdev_s *priv = (struct stm32_usbdev_s *)dev;
+ struct stm32_ep_s *privep = NULL;
+ uint8_t epset = STM32_ENDP_ALLSET;
+ int bufno;
+
+ usbtrace(TRACE_DEVALLOCEP, (uint16_t)epno);
+#ifdef CONFIG_DEBUG
+ if (!dev)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return NULL;
+ }
+#endif
+
+ /* Ignore any direction bits in the logical address */
+
+ epno = USB_EPNO(epno);
+
+ /* A logical address of 0 means that any endpoint will do */
+
+ if (epno > 0)
+ {
+ /* Otherwise, we will return the endpoint structure only for the requested
+ * 'logical' endpoint. All of the other checks will still be performed.
+ *
+ * First, verify that the logical endpoint is in the range supported by
+ * by the hardware.
+ */
+
+ if (epno >= STM32_NENDPOINTS)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPNO), (uint16_t)epno);
+ return NULL;
+ }
+
+ /* Convert the logical address to a physical OUT endpoint address and
+ * remove all of the candidate endpoints from the bitset except for the
+ * the IN/OUT pair for this logical address.
+ */
+
+ epset = STM32_ENDP_BIT(epno);
+ }
+
+ /* Check if the selected endpoint number is available */
+
+ privep = stm32_epreserve(priv, epset);
+ if (!privep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPRESERVE), (uint16_t)epset);
+ goto errout;
+ }
+ epno = USB_EPNO(privep->ep.eplog);
+
+ /* Allocate a PMA buffer for this endpoint */
+
+#warning "REVISIT: Should configure BULK EPs using double buffer feature"
+ bufno = stm32_epallocpma(priv);
+ if (bufno < 0)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPBUFFER), 0);
+ goto errout_with_ep;
+ }
+ privep->bufno = (uint8_t)bufno;
+ return &privep->ep;
+
+errout_with_ep:
+ stm32_epunreserve(priv, privep);
+errout:
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: stm32_freeep
+ ****************************************************************************/
+
+static void stm32_freeep(struct usbdev_s *dev, struct usbdev_ep_s *ep)
+{
+ struct stm32_usbdev_s *priv;
+ struct stm32_ep_s *privep;
+
+#ifdef CONFIG_DEBUG
+ if (!dev || !ep)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return;
+ }
+#endif
+ priv = (struct stm32_usbdev_s *)dev;
+ privep = (struct stm32_ep_s *)ep;
+ usbtrace(TRACE_DEVFREEEP, (uint16_t)USB_EPNO(ep->eplog));
+
+ if (priv && privep)
+ {
+ /* Free the PMA buffer assigned to this endpoint */
+
+ stm32_epfreepma(priv, privep);
+
+ /* Mark the endpoint as available */
+
+ stm32_epunreserve(priv, privep);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_getframe
+ ****************************************************************************/
+
+static int stm32_getframe(struct usbdev_s *dev)
+{
+ uint16_t fnr;
+
+#ifdef CONFIG_DEBUG
+ if (!dev)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+
+ /* Return the last frame number detected by the hardware */
+
+ fnr = stm32_getreg(STM32_USB_FNR);
+ usbtrace(TRACE_DEVGETFRAME, fnr);
+ return (fnr & USB_FNR_FN_MASK);
+}
+
+/****************************************************************************
+ * Name: stm32_wakeup
+ ****************************************************************************/
+
+static int stm32_wakeup(struct usbdev_s *dev)
+{
+ struct stm32_usbdev_s *priv = (struct stm32_usbdev_s *)dev;
+ irqstate_t flags;
+
+ usbtrace(TRACE_DEVWAKEUP, 0);
+#ifdef CONFIG_DEBUG
+ if (!dev)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+
+ /* Start the resume sequence. The actual resume steps will be driven
+ * by the ESOF interrupt.
+ */
+
+ flags = irqsave();
+ stm32_initresume(priv);
+ priv->rsmstate = RSMSTATE_STARTED;
+
+ /* Disable the SUSP interrupt (until we are fully resumed), disable
+ * the WKUP interrupt (we are already waking up), and enable the
+ * ESOF interrupt that will drive the resume operations. Clear any
+ * pending ESOF interrupt.
+ */
+
+ stm32_setimask(priv, USB_CNTR_ESOFM, USB_CNTR_WKUPM|USB_CNTR_SUSPM);
+ stm32_putreg(~USB_ISTR_ESOF, STM32_USB_ISTR);
+ irqrestore(flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_selfpowered
+ ****************************************************************************/
+
+static int stm32_selfpowered(struct usbdev_s *dev, bool selfpowered)
+{
+ struct stm32_usbdev_s *priv = (struct stm32_usbdev_s *)dev;
+
+ usbtrace(TRACE_DEVSELFPOWERED, (uint16_t)selfpowered);
+
+#ifdef CONFIG_DEBUG
+ if (!dev)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -ENODEV;
+ }
+#endif
+
+ priv->selfpowered = selfpowered;
+ return OK;
+}
+
+/****************************************************************************
+ * Initialization/Reset
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_reset
+ ****************************************************************************/
+
+static void stm32_reset(struct stm32_usbdev_s *priv)
+{
+ int epno;
+
+ /* Put the USB controller in reset, disable all interrupts */
+
+ stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR);
+
+ /* Tell the class driver that we are disconnected. The class driver
+ * should then accept any new configurations.
+ */
+
+ CLASS_DISCONNECT(priv->driver, &priv->usbdev);
+
+ /* Reset the device state structure */
+
+ priv->devstate = DEVSTATE_IDLE;
+ priv->rsmstate = RSMSTATE_IDLE;
+ priv->rxpending = false;
+
+ /* Reset endpoints */
+
+ for (epno = 0; epno < STM32_NENDPOINTS; epno++)
+ {
+ struct stm32_ep_s *privep = &priv->eplist[epno];
+
+ /* Cancel any queued requests. Since they are canceled
+ * with status -ESHUTDOWN, then will not be requeued
+ * until the configuration is reset. NOTE: This should
+ * not be necessary... the CLASS_DISCONNECT above should
+ * result in the class implementation calling stm32_epdisable
+ * for each of its configured endpoints.
+ */
+
+ stm32_cancelrequests(privep);
+
+ /* Reset endpoint status */
+
+ privep->stalled = false;
+ privep->halted = false;
+ privep->txbusy = false;
+ privep->txnullpkt = false;
+ }
+
+ /* Re-configure the USB controller in its initial, unconnected state */
+
+ stm32_hwreset(priv);
+ priv->usbdev.speed = USB_SPEED_FULL;
+}
+
+/****************************************************************************
+ * Name: stm32_hwreset
+ ****************************************************************************/
+
+static void stm32_hwreset(struct stm32_usbdev_s *priv)
+{
+ /* Put the USB controller into reset, clear all interrupt enables */
+
+ stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR);
+
+ /* Disable interrupts (and perhaps take the USB controller out of reset) */
+
+ priv->imask = 0;
+ stm32_putreg(priv->imask, STM32_USB_CNTR);
+
+ /* Set the STM32 BTABLE address */
+
+ stm32_putreg(STM32_BTABLE_ADDRESS & 0xfff8, STM32_USB_BTABLE);
+
+ /* Initialize EP0 */
+
+ stm32_seteptype(EP0, USB_EPR_EPTYPE_CONTROL);
+ stm32_seteptxstatus(EP0, USB_EPR_STATTX_NAK);
+ stm32_seteprxaddr(EP0, STM32_EP0_RXADDR);
+ stm32_seteprxcount(EP0, STM32_EP0MAXPACKET);
+ stm32_seteptxaddr(EP0, STM32_EP0_TXADDR);
+ stm32_clrstatusout(EP0);
+ stm32_seteprxstatus(EP0, USB_EPR_STATRX_VALID);
+
+ /* Set the device to respond on default address */
+
+ stm32_setdevaddr(priv, 0);
+
+ /* Clear any pending interrupts */
+
+ stm32_putreg(0, STM32_USB_ISTR);
+
+ /* Enable interrupts at the USB controller */
+
+ stm32_setimask(priv, STM32_CNTR_SETUP, (USB_CNTR_ALLINTS & ~STM32_CNTR_SETUP));
+ stm32_dumpep(EP0);
+}
+
+/****************************************************************************
+ * Name: stm32_hwsetup
+ ****************************************************************************/
+
+static void stm32_hwsetup(struct stm32_usbdev_s *priv)
+{
+ int epno;
+
+ /* Power the USB controller, put the USB controller into reset, disable
+ * all USB interrupts
+ */
+
+ stm32_putreg(USB_CNTR_FRES|USB_CNTR_PDWN, STM32_USB_CNTR);
+
+ /* Disconnect the device / disable the pull-up. We don't want the
+ * host to enumerate us until the class driver is registered.
+ */
+
+ stm32_usbpullup(&priv->usbdev, false);
+
+ /* Initialize the device state structure. NOTE: many fields
+ * have the initial value of zero and, hence, are not explicitly
+ * initialized here.
+ */
+
+ memset(priv, 0, sizeof(struct stm32_usbdev_s));
+ priv->usbdev.ops = &g_devops;
+ priv->usbdev.ep0 = &priv->eplist[EP0].ep;
+ priv->epavail = STM32_ENDP_ALLSET & ~STM32_ENDP_BIT(EP0);
+ priv->bufavail = STM32_BUFFER_ALLSET & ~STM32_BUFFER_EP0;
+
+ /* Initialize the endpoint list */
+
+ for (epno = 0; epno < STM32_NENDPOINTS; epno++)
+ {
+ /* Set endpoint operations, reference to driver structure (not
+ * really necessary because there is only one controller), and
+ * the (physical) endpoint number which is just the index to the
+ * endpoint.
+ */
+
+ priv->eplist[epno].ep.ops = &g_epops;
+ priv->eplist[epno].dev = priv;
+ priv->eplist[epno].ep.eplog = epno;
+
+ /* We will use a fixed maxpacket size for all endpoints (perhaps
+ * ISOC endpoints could have larger maxpacket???). A smaller
+ * packet size can be selected when the endpoint is configured.
+ */
+
+ priv->eplist[epno].ep.maxpacket = STM32_MAXPACKET_SIZE;
+ }
+
+ /* Select a smaller endpoint size for EP0 */
+
+#if STM32_EP0MAXPACKET < STM32_MAXPACKET_SIZE
+ priv->eplist[EP0].ep.maxpacket = STM32_EP0MAXPACKET;
+#endif
+
+ /* Configure the USB controller. USB uses the following GPIO pins:
+ *
+ * PA9 - VBUS
+ * PA10 - ID
+ * PA11 - DM
+ * PA12 - DP
+ *
+ * "As soon as the USB is enabled, these pins [DM and DP] are connected to
+ * the USB internal transceiver automatically."
+ */
+
+ /* Power up the USB controller, holding it in reset. There is a delay of
+ * about 1uS after applying power before the USB will behave predictably.
+ * A 5MS delay is more than enough. NOTE that we leave the USB controller
+ * in the reset state; the hardware will not be initialized until the
+ * class driver has been bound.
+ */
+
+ stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR);
+ up_mdelay(5);
+}
+
+/****************************************************************************
+ * Name: stm32_hwshutdown
+ ****************************************************************************/
+
+static void stm32_hwshutdown(struct stm32_usbdev_s *priv)
+{
+ priv->usbdev.speed = USB_SPEED_UNKNOWN;
+
+ /* Disable all interrupts and force the USB controller into reset */
+
+ stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR);
+
+ /* Clear any pending interrupts */
+
+ stm32_putreg(0, STM32_USB_ISTR);
+
+ /* Disconnect the device / disable the pull-up */
+
+ stm32_usbpullup(&priv->usbdev, false);
+
+ /* Power down the USB controller */
+
+ stm32_putreg(USB_CNTR_FRES|USB_CNTR_PDWN, STM32_USB_CNTR);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: up_usbinitialize
+ * Description:
+ * Initialize the USB driver
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void up_usbinitialize(void)
+{
+ /* For now there is only one USB controller, but we will always refer to
+ * it using a pointer to make any future ports to multiple USB controllers
+ * easier.
+ */
+
+ struct stm32_usbdev_s *priv = &g_usbdev;
+
+ usbtrace(TRACE_DEVINIT, 0);
+ stm32_checksetup();
+
+ /* Power up the USB controller, but leave it in the reset state */
+
+ stm32_hwsetup(priv);
+
+ /* Attach USB controller interrupt handlers. The hardware will not be
+ * initialized and interrupts will not be enabled until the class device
+ * driver is bound. Getting the IRQs here only makes sure that we have
+ * them when we need them later.
+ */
+
+ if (irq_attach(STM32_IRQ_USBHPCANTX, stm32_hpinterrupt) != 0)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_IRQREGISTRATION),
+ (uint16_t)STM32_IRQ_USBHPCANTX);
+ goto errout;
+ }
+
+ if (irq_attach(STM32_IRQ_USBLPCANRX0, stm32_lpinterrupt) != 0)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_IRQREGISTRATION),
+ (uint16_t)STM32_IRQ_USBLPCANRX0);
+ goto errout;
+ }
+ return;
+
+errout:
+ up_usbuninitialize();
+}
+
+/****************************************************************************
+ * Name: up_usbuninitialize
+ * Description:
+ * Initialize the USB driver
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void up_usbuninitialize(void)
+{
+ /* For now there is only one USB controller, but we will always refer to
+ * it using a pointer to make any future ports to multiple USB controllers
+ * easier.
+ */
+
+ struct stm32_usbdev_s *priv = &g_usbdev;
+ irqstate_t flags;
+
+ flags = irqsave();
+ usbtrace(TRACE_DEVUNINIT, 0);
+
+ /* Disable and detach the USB IRQs */
+
+ up_disable_irq(STM32_IRQ_USBHPCANTX);
+ up_disable_irq(STM32_IRQ_USBLPCANRX0);
+ irq_detach(STM32_IRQ_USBHPCANTX);
+ irq_detach(STM32_IRQ_USBLPCANRX0);
+
+ if (priv->driver)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DRIVERREGISTERED), 0);
+ usbdev_unregister(priv->driver);
+ }
+
+ /* Put the hardware in an inactive state */
+
+ stm32_hwshutdown(priv);
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: usbdev_register
+ *
+ * Description:
+ * Register a USB device class driver. The class driver's bind() method will be
+ * called to bind it to a USB device driver.
+ *
+ ****************************************************************************/
+
+int usbdev_register(struct usbdevclass_driver_s *driver)
+{
+ /* For now there is only one USB controller, but we will always refer to
+ * it using a pointer to make any future ports to multiple USB controllers
+ * easier.
+ */
+
+ struct stm32_usbdev_s *priv = &g_usbdev;
+ int ret;
+
+ usbtrace(TRACE_DEVREGISTER, 0);
+
+#ifdef CONFIG_DEBUG
+ if (!driver || !driver->ops->bind || !driver->ops->unbind ||
+ !driver->ops->disconnect || !driver->ops->setup)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+
+ if (priv->driver)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DRIVER), 0);
+ return -EBUSY;
+ }
+#endif
+
+ /* First hook up the driver */
+
+ priv->driver = driver;
+
+ /* Then bind the class driver */
+
+ ret = CLASS_BIND(driver, &priv->usbdev);
+ if (ret)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BINDFAILED), (uint16_t)-ret);
+ priv->driver = NULL;
+ }
+ else
+ {
+ /* Setup the USB controller -- enabling interrupts at the USB controller */
+
+ stm32_hwreset(priv);
+
+ /* Enable USB controller interrupts at the NVIC */
+
+ up_enable_irq(STM32_IRQ_USBHPCANTX);
+ up_enable_irq(STM32_IRQ_USBLPCANRX0);
+
+ /* Set the interrrupt priority */
+
+ up_prioritize_irq(STM32_IRQ_USBHPCANTX, CONFIG_USB_PRI);
+ up_prioritize_irq(STM32_IRQ_USBLPCANRX0, CONFIG_USB_PRI);
+
+ /* Enable pull-up to connect the device. The host should enumerate us
+ * some time after this
+ */
+
+ stm32_usbpullup(&priv->usbdev, true);
+ priv->usbdev.speed = USB_SPEED_FULL;
+ }
+ return ret;
+}
+
+/****************************************************************************
+ * Name: usbdev_unregister
+ *
+ * Description:
+ * Un-register usbdev class driver. If the USB device is connected to a
+ * USB host, it will first disconnect(). The driver is also requested to
+ * unbind() and clean up any device state, before this procedure finally
+ * returns.
+ *
+ ****************************************************************************/
+
+int usbdev_unregister(struct usbdevclass_driver_s *driver)
+{
+ /* For now there is only one USB controller, but we will always refer to
+ * it using a pointer to make any future ports to multiple USB controllers
+ * easier.
+ */
+
+ struct stm32_usbdev_s *priv = &g_usbdev;
+ irqstate_t flags;
+
+ usbtrace(TRACE_DEVUNREGISTER, 0);
+
+#ifdef CONFIG_DEBUG
+ if (driver != priv->driver)
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+
+ /* Reset the hardware and cancel all requests. All requests must be
+ * canceled while the class driver is still bound.
+ */
+
+ flags = irqsave();
+ stm32_reset(priv);
+
+ /* Unbind the class driver */
+
+ CLASS_UNBIND(driver, &priv->usbdev);
+
+ /* Disable USB controller interrupts (but keep them attached) */
+
+ up_disable_irq(STM32_IRQ_USBHPCANTX);
+ up_disable_irq(STM32_IRQ_USBLPCANRX0);
+
+ /* Put the hardware in an inactive state. Then bring the hardware back up
+ * in the reset state (this is probably not necessary, the stm32_reset()
+ * call above was probably sufficient).
+ */
+
+ stm32_hwshutdown(priv);
+ stm32_hwsetup(priv);
+
+ /* Unhook the driver */
+
+ priv->driver = NULL;
+ irqrestore(flags);
+ return OK;
+}
+
+#endif /* CONFIG_USBDEV && CONFIG_STM32_USB */
diff --git a/nuttx/arch/arm/src/stm32/stm32_usbdev.h b/nuttx/arch/arm/src/stm32/stm32_usbdev.h
new file mode 100644
index 000000000..a1af471b2
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_usbdev.h
@@ -0,0 +1,98 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_usbdev.h
+ *
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_STM32_USBDEV_H
+#define __ARCH_ARM_SRC_STM32_STM32_USBDEV_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/usb/usbdev.h>
+#include <stdint.h>
+
+#include "chip.h"
+#include "chip/stm32_usbdev.h"
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Name: stm32_usbpullup
+ *
+ * Description:
+ * If USB is supported and the board supports a pullup via GPIO (for USB software
+ * connect and disconnect), then the board software must provide stm32_pullup.
+ * See include/nuttx/usb/usbdev.h for additional description of this method.
+ * Alternatively, if no pull-up GPIO the following EXTERN can be redefined to be
+ * NULL.
+ *
+ ************************************************************************************/
+
+EXTERN int stm32_usbpullup(FAR struct usbdev_s *dev, bool enable);
+
+/************************************************************************************
+ * Name: stm32_usbsuspend
+ *
+ * Description:
+ * Board logic must provide the stm32_usbsuspend logic if the USBDEV driver is
+ * used. This function is called whenever the USB enters or leaves suspend mode.
+ * This is an opportunity for the board logic to shutdown clocks, power, etc.
+ * while the USB is suspended.
+ *
+ ************************************************************************************/
+
+EXTERN void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_USBDEV_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_usbhost.c b/nuttx/arch/arm/src/stm32/stm32_usbhost.c
new file mode 100644
index 000000000..4bf6d646d
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_usbhost.c
@@ -0,0 +1,2695 @@
+/*******************************************************************************
+ * arch/arm/src/stm32/stm32_usbhost.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Authors: 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 <stdlib.h>
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/usb/usb.h>
+#include <nuttx/usb/usbhost.h>
+
+#include <arch/irq.h>
+
+#include "chip.h" /* Includes default GPIO settings */
+#include <arch/board/board.h> /* May redefine GPIO settings */
+
+#include "up_arch.h"
+#include "up_internal.h"
+
+#include "stm32_usbhost.h"
+
+/*******************************************************************************
+ * Definitions
+ *******************************************************************************/
+
+/* Configuration ***************************************************************/
+
+/* All I/O buffers must lie in AHB SRAM because of the OHCI DMA. It might be
+ * okay if no I/O buffers are used *IF* the application can guarantee that all
+ * end-user I/O buffers reside in AHB SRAM.
+ */
+
+#if STM32_IOBUFFERS < 1
+# warning "No IO buffers allocated"
+#endif
+
+/* OHCI Setup ******************************************************************/
+/* Frame Interval / Periodic Start */
+
+#define BITS_PER_FRAME 12000
+#define FI (BITS_PER_FRAME-1)
+#define FSMPS ((6 * (FI - 210)) / 7)
+#define DEFAULT_FMINTERVAL ((FSMPS << OHCI_FMINT_FSMPS_SHIFT) | FI)
+#define DEFAULT_PERSTART (((9 * BITS_PER_FRAME) / 10) - 1)
+
+/* CLKCTRL enable bits */
+
+#define STM32_CLKCTRL_ENABLES (USBOTG_CLK_HOSTCLK|USBOTG_CLK_PORTSELCLK|USBOTG_CLK_AHBCLK)
+
+/* Interrupt enable bits */
+
+#ifdef CONFIG_DEBUG_USB
+# define STM32_DEBUG_INTS (OHCI_INT_SO|OHCI_INT_RD|OHCI_INT_UE|OHCI_INT_OC)
+#else
+# define STM32_DEBUG_INTS 0
+#endif
+
+#define STM32_NORMAL_INTS (OHCI_INT_WDH|OHCI_INT_RHSC)
+#define STM32_ALL_INTS (STM32_NORMAL_INTS|STM32_DEBUG_INTS)
+
+/* Dump GPIO registers */
+
+#if defined(CONFIG_STM32_USBHOST_REGDEBUG) && defined(CONFIG_DEBUG_GPIO)
+# define usbhost_dumpgpio() \
+ do { \
+ stm32_dumpgpio(GPIO_USB_DP, "D+ P0.29; D- P0.30"); \
+ stm32_dumpgpio(GPIO_USB_UPLED, "LED P1:18; PPWR P1:19 PWRD P1:22 PVRCR P1:27"); \
+ } while (0);
+#else
+# define usbhost_dumpgpio()
+#endif
+
+/* USB Host Memory *************************************************************/
+
+/* Helper definitions */
+
+#define HCCA ((struct ohci_hcca_s *)STM32_HCCA_BASE)
+#define TDTAIL ((struct stm32_gtd_s *)STM32_TDTAIL_ADDR)
+#define EDCTRL ((struct stm32_ed_s *)STM32_EDCTRL_ADDR)
+
+/* Periodic intervals 2, 4, 8, 16,and 32 supported */
+
+#define MIN_PERINTERVAL 2
+#define MAX_PERINTERVAL 32
+
+/* Descriptors *****************************************************************/
+
+/* TD delay interrupt value */
+
+#define TD_DELAY(n) (uint32_t)((n) << GTD_STATUS_DI_SHIFT)
+
+/*******************************************************************************
+ * Private Types
+ *******************************************************************************/
+
+/* This structure retains the state of the USB host controller */
+
+struct stm32_usbhost_s
+{
+ /* Common device fields. This must be the first thing defined in the
+ * structure so that it is possible to simply cast from struct usbhost_s
+ * to structstm32_usbhost_s.
+ */
+
+ struct usbhost_driver_s drvr;
+
+ /* The bound device class driver */
+
+ struct usbhost_class_s *class;
+
+ /* Driver status */
+
+ volatile bool connected; /* Connected to device */
+ volatile bool lowspeed; /* Low speed device attached. */
+ volatile bool rhswait; /* TRUE: Thread is waiting for Root Hub Status change */
+#ifndef CONFIG_USBHOST_INT_DISABLE
+ uint8_t ininterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */
+ uint8_t outinterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */
+#endif
+ sem_t exclsem; /* Support mutually exclusive access */
+ sem_t rhssem; /* Semaphore to wait Writeback Done Head event */
+};
+
+/* The OCHI expects the size of an endpoint descriptor to be 16 bytes.
+ * However, the size allocated for an endpoint descriptor is 32 bytes in
+ * stm32_ohciram.h. This extra 16-bytes is used by the OHCI host driver in
+ * order to maintain additional endpoint-specific data.
+ */
+
+struct stm32_ed_s
+{
+ /* Hardware specific fields */
+
+ struct ohci_ed_s hw;
+
+ /* Software specific fields */
+
+ uint8_t xfrtype; /* Transfer type. See SB_EP_ATTR_XFER_* in usb.h */
+ uint8_t interval; /* Periodic EP polling interval: 2, 4, 6, 16, or 32 */
+ volatile uint8_t tdstatus; /* TD control status bits from last Writeback Done Head event */
+ volatile bool wdhwait; /* TRUE: Thread is waiting for WDH interrupt */
+ sem_t wdhsem; /* Semaphore used to wait for Writeback Done Head event */
+ /* Unused bytes follow, depending on the size of sem_t */
+};
+
+/* The OCHI expects the size of an transfer descriptor to be 16 bytes.
+ * However, the size allocated for an endpoint descriptor is 32 bytes in
+ * stm32_ohciram.h. This extra 16-bytes is used by the OHCI host driver in
+ * order to maintain additional endpoint-specific data.
+ */
+
+struct stm32_gtd_s
+{
+ /* Hardware specific fields */
+
+ struct ohci_gtd_s hw;
+
+ /* Software specific fields */
+
+ struct stm32_ed_s *ed; /* Pointer to parent ED */
+ uint8_t pad[12];
+};
+
+/* The following is used to manage lists of free EDs, TDs, and TD buffers */
+
+struct stm32_list_s
+{
+ struct stm32_list_s *flink; /* Link to next buffer in the list */
+ /* Variable length buffer data follows */
+};
+
+/*******************************************************************************
+ * Private Function Prototypes
+ *******************************************************************************/
+
+/* Register operations ********************************************************/
+
+#ifdef CONFIG_STM32_USBHOST_REGDEBUG
+static void stm32_printreg(uint32_t addr, uint32_t val, bool iswrite);
+static void stm32_checkreg(uint32_t addr, uint32_t val, bool iswrite);
+static uint32_t stm32_getreg(uint32_t addr);
+static void stm32_putreg(uint32_t val, uint32_t addr);
+#else
+# define stm32_getreg(addr) getreg32(addr)
+# define stm32_putreg(val,addr) putreg32(val,addr)
+#endif
+
+/* Semaphores ******************************************************************/
+
+static void stm32_takesem(sem_t *sem);
+#define stm32_givesem(s) sem_post(s);
+
+/* Byte stream access helper functions *****************************************/
+
+static inline uint16_t stm32_getle16(const uint8_t *val);
+static void stm32_putle16(uint8_t *dest, uint16_t val);
+
+/* OHCI memory pool helper functions *******************************************/
+
+static inline void stm32_edfree(struct stm32_ed_s *ed);
+static struct stm32_gtd_s *stm32_tdalloc(void);
+static void stm32_tdfree(struct stm32_gtd_s *buffer);
+static uint8_t *stm32_tballoc(void);
+static void stm32_tbfree(uint8_t *buffer);
+#if STM32_IOBUFFERS > 0
+static uint8_t *stm32_allocio(void);
+static void stm32_freeio(uint8_t *buffer);
+#endif
+
+/* ED list helper functions ****************************************************/
+
+static inline int stm32_addbulked(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed);
+static inline int stm32_rembulked(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed);
+
+#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE)
+static unsigned int stm32_getinterval(uint8_t interval);
+static void stm32_setinttab(uint32_t value, unsigned int interval, unsigned int offset);
+#endif
+
+static inline int stm32_addinted(struct stm32_usbhost_s *priv,
+ const FAR struct usbhost_epdesc_s *epdesc,
+ struct stm32_ed_s *ed);
+static inline int stm32_reminted(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed);
+
+static inline int stm32_addisoced(struct stm32_usbhost_s *priv,
+ const FAR struct usbhost_epdesc_s *epdesc,
+ struct stm32_ed_s *ed);
+static inline int stm32_remisoced(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed);
+
+/* Descriptor helper functions *************************************************/
+
+static int stm32_enqueuetd(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed, uint32_t dirpid,
+ uint32_t toggle, volatile uint8_t *buffer,
+ size_t buflen);
+static int stm32_ctrltd(struct stm32_usbhost_s *priv, uint32_t dirpid,
+ uint8_t *buffer, size_t buflen);
+
+/* Interrupt handling **********************************************************/
+
+static int stm32_usbinterrupt(int irq, FAR void *context);
+
+/* USB host controller operations **********************************************/
+
+static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected);
+static int stm32_enumerate(FAR struct usbhost_driver_s *drvr);
+static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
+ uint16_t maxpacketsize);
+static int stm32_epalloc(FAR struct usbhost_driver_s *drvr,
+ const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep);
+static int stm32_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
+static int stm32_alloc(FAR struct usbhost_driver_s *drvr,
+ FAR uint8_t **buffer, FAR size_t *maxlen);
+static int stm32_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer);
+static int stm32_ioalloc(FAR struct usbhost_driver_s *drvr,
+ FAR uint8_t **buffer, size_t buflen);
+static int stm32_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer);
+static int stm32_ctrlin(FAR struct usbhost_driver_s *drvr,
+ FAR const struct usb_ctrlreq_s *req,
+ FAR uint8_t *buffer);
+static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr,
+ FAR const struct usb_ctrlreq_s *req,
+ FAR const uint8_t *buffer);
+static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
+ FAR uint8_t *buffer, size_t buflen);
+static void stm32_disconnect(FAR struct usbhost_driver_s *drvr);
+
+/* Initialization **************************************************************/
+
+static inline void stm32_ep0init(struct stm32_usbhost_s *priv);
+
+/*******************************************************************************
+ * Private Data
+ *******************************************************************************/
+
+/* In this driver implementation, support is provided for only a single a single
+ * USB device. All status information can be simply retained in a single global
+ * instance.
+ */
+
+static struct stm32_usbhost_s g_usbhost =
+{
+ .drvr =
+ {
+ .wait = stm32_wait,
+ .enumerate = stm32_enumerate,
+ .ep0configure = stm32_ep0configure,
+ .epalloc = stm32_epalloc,
+ .epfree = stm32_epfree,
+ .alloc = stm32_alloc,
+ .free = stm32_free,
+ .ioalloc = stm32_ioalloc,
+ .iofree = stm32_iofree,
+ .ctrlin = stm32_ctrlin,
+ .ctrlout = stm32_ctrlout,
+ .transfer = stm32_transfer,
+ .disconnect = stm32_disconnect,
+ },
+ .class = NULL,
+};
+
+/* This is a free list of EDs and TD buffers */
+
+static struct stm32_list_s *g_edfree; /* List of unused EDs */
+static struct stm32_list_s *g_tdfree; /* List of unused TDs */
+static struct stm32_list_s *g_tbfree; /* List of unused transfer buffers */
+#if STM32_IOBUFFERS > 0
+static struct stm32_list_s *g_iofree; /* List of unused I/O buffers */
+#endif
+
+/*******************************************************************************
+ * Public Data
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Private Functions
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: stm32_printreg
+ *
+ * Description:
+ * Print the contents of an STM32xx register operation
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_STM32_USBHOST_REGDEBUG
+static void stm32_printreg(uint32_t addr, uint32_t val, bool iswrite)
+{
+ lldbg("%08x%s%08x\n", addr, iswrite ? "<-" : "->", val);
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_checkreg
+ *
+ * Description:
+ * Get the contents of an STM32 register
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_STM32_USBHOST_REGDEBUG
+static void stm32_checkreg(uint32_t addr, uint32_t val, bool iswrite)
+{
+ static uint32_t prevaddr = 0;
+ static uint32_t preval = 0;
+ static uint32_t count = 0;
+ static bool prevwrite = false;
+
+ /* Is this the same value that we read from/wrote to the same register last time?
+ * Are we polling the register? If so, suppress the output.
+ */
+
+ if (addr == prevaddr && val == preval && prevwrite == iswrite)
+ {
+ /* Yes.. Just increment the count */
+
+ count++;
+ }
+ else
+ {
+ /* No this is a new address or value or operation. Were there any
+ * duplicate accesses before this one?
+ */
+
+ if (count > 0)
+ {
+ /* Yes.. Just one? */
+
+ if (count == 1)
+ {
+ /* Yes.. Just one */
+
+ stm32_printreg(prevaddr, preval, prevwrite);
+ }
+ else
+ {
+ /* No.. More than one. */
+
+ lldbg("[repeats %d more times]\n", count);
+ }
+ }
+
+ /* Save the new address, value, count, and operation for next time */
+
+ prevaddr = addr;
+ preval = val;
+ count = 0;
+ prevwrite = iswrite;
+
+ /* Show the new regisgter access */
+
+ stm32_printreg(addr, val, iswrite);
+ }
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_getreg
+ *
+ * Description:
+ * Get the contents of an STM32 register
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_STM32_USBHOST_REGDEBUG
+static uint32_t stm32_getreg(uint32_t addr)
+{
+ /* Read the value from the register */
+
+ uint32_t val = getreg32(addr);
+
+ /* Check if we need to print this value */
+
+ stm32_checkreg(addr, val, false);
+ return val;
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_putreg
+ *
+ * Description:
+ * Set the contents of an STM32 register to a value
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_STM32_USBHOST_REGDEBUG
+static void stm32_putreg(uint32_t val, uint32_t addr)
+{
+ /* Check if we need to print this value */
+
+ stm32_checkreg(addr, val, true);
+
+ /* Write the value */
+
+ putreg32(val, addr);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_takesem
+ *
+ * Description:
+ * This is just a wrapper to handle the annoying behavior of semaphore
+ * waits that return due to the receipt of a signal.
+ *
+ *******************************************************************************/
+
+static void stm32_takesem(sem_t *sem)
+{
+ /* Take the semaphore (perhaps waiting) */
+
+ while (sem_wait(sem) != 0)
+ {
+ /* The only case that an error should occr here is if the wait was
+ * awakened by a signal.
+ */
+
+ ASSERT(errno == EINTR);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_getle16
+ *
+ * Description:
+ * Get a (possibly unaligned) 16-bit little endian value.
+ *
+ *******************************************************************************/
+
+static inline uint16_t stm32_getle16(const uint8_t *val)
+{
+ return (uint16_t)val[1] << 8 | (uint16_t)val[0];
+}
+
+/****************************************************************************
+ * Name: stm32_putle16
+ *
+ * Description:
+ * Put a (possibly unaligned) 16-bit little endian value.
+ *
+ *******************************************************************************/
+
+static void stm32_putle16(uint8_t *dest, uint16_t val)
+{
+ dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
+ dest[1] = val >> 8;
+}
+
+/*******************************************************************************
+ * Name: stm32_edfree
+ *
+ * Description:
+ * Return an endpoint descriptor to the free list
+ *
+ *******************************************************************************/
+
+static inline void stm32_edfree(struct stm32_ed_s *ed)
+{
+ struct stm32_list_s *entry = (struct stm32_list_s *)ed;
+
+ /* Put the ED back into the free list */
+
+ entry->flink = g_edfree;
+ g_edfree = entry;
+}
+
+/*******************************************************************************
+ * Name: stm32_tdalloc
+ *
+ * Description:
+ * Allocate an transfer descriptor from the free list
+ *
+ * Assumptions:
+ * - Never called from an interrupt handler.
+ * - Protected from conconcurrent access to the TD pool by the interrupt
+ * handler
+ * - Protection from re-entrance must be assured by the caller
+ *
+ *******************************************************************************/
+
+static struct stm32_gtd_s *stm32_tdalloc(void)
+{
+ struct stm32_gtd_s *ret;
+ irqstate_t flags;
+
+ /* Disable interrupts momentarily so that stm32_tdfree is not called from the
+ * interrupt handler.
+ */
+
+ flags = irqsave();
+ ret = (struct stm32_gtd_s *)g_tdfree;
+ if (ret)
+ {
+ g_tdfree = ((struct stm32_list_s*)ret)->flink;
+ }
+
+ irqrestore(flags);
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_tdfree
+ *
+ * Description:
+ * Return an transfer descriptor to the free list
+ *
+ * Assumptions:
+ * - Only called from the WDH interrupt handler (and during initialization).
+ * - Interrupts are disabled in any case.
+ *
+ *******************************************************************************/
+
+static void stm32_tdfree(struct stm32_gtd_s *td)
+{
+ struct stm32_list_s *tdfree = (struct stm32_list_s *)td;
+
+ /* This should not happen but just to be safe, don't free the common, pre-
+ * allocated tail TD.
+ */
+
+ if (tdfree != NULL && td != TDTAIL)
+ {
+ tdfree->flink = g_tdfree;
+ g_tdfree = tdfree;
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_tballoc
+ *
+ * Description:
+ * Allocate an request/descriptor transfer buffer from the free list
+ *
+ * Assumptions:
+ * - Never called from an interrupt handler.
+ * - Protection from re-entrance must be assured by the caller
+ *
+ *******************************************************************************/
+
+static uint8_t *stm32_tballoc(void)
+{
+ uint8_t *ret = (uint8_t *)g_tbfree;
+ if (ret)
+ {
+ g_tbfree = ((struct stm32_list_s*)ret)->flink;
+ }
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_tbfree
+ *
+ * Description:
+ * Return an request/descriptor transfer buffer to the free list
+ *
+ *******************************************************************************/
+
+static void stm32_tbfree(uint8_t *buffer)
+{
+ struct stm32_list_s *tbfree = (struct stm32_list_s *)buffer;
+
+ if (tbfree)
+ {
+ tbfree->flink = g_tbfree;
+ g_tbfree = tbfree;
+ }
+}
+
+/*******************************************************************************
+ * Name: stm32_allocio
+ *
+ * Description:
+ * Allocate an IO buffer from the free list
+ *
+ * Assumptions:
+ * - Never called from an interrupt handler.
+ * - Protection from re-entrance must be assured by the caller
+ *
+ *******************************************************************************/
+
+#if STM32_IOBUFFERS > 0
+static uint8_t *stm32_allocio(void)
+{
+ uint8_t *ret = (uint8_t *)g_iofree;
+ if (ret)
+ {
+ g_iofree = ((struct stm32_list_s*)ret)->flink;
+ }
+ return ret;
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_freeio
+ *
+ * Description:
+ * Return an TD buffer to the free list
+ *
+ *******************************************************************************/
+
+#if STM32_IOBUFFERS > 0
+static void stm32_freeio(uint8_t *buffer)
+{
+ struct stm32_list_s *iofree = (struct stm32_list_s *)buffer;
+ iofree->flink = g_iofree;
+ g_iofree = iofree;
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_addbulked
+ *
+ * Description:
+ * Helper function to add an ED to the bulk list.
+ *
+ *******************************************************************************/
+
+static inline int stm32_addbulked(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_BULK_DISABLE
+ uint32_t regval;
+
+ /* Add the new bulk ED to the head of the bulk list */
+
+ ed->hw.nexted = stm32_getreg(STM32_USBHOST_BULKHEADED);
+ stm32_putreg((uint32_t)ed, STM32_USBHOST_BULKHEADED);
+
+ /* BulkListEnable. This bit is set to enable the processing of the
+ * Bulk list. Note: once enabled, it remains. We really should
+ * never modify the bulk list while BLE is set.
+ */
+
+ regval = stm32_getreg(STM32_USBHOST_CTRL);
+ regval |= OHCI_CTRL_BLE;
+ stm32_putreg(regval, STM32_USBHOST_CTRL);
+ return OK;
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*******************************************************************************
+ * Name: stm32_rembulked
+ *
+ * Description:
+ * Helper function remove an ED from the bulk list.
+ *
+ *******************************************************************************/
+
+static inline int stm32_rembulked(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_BULK_DISABLE
+ struct stm32_ed_s *curr;
+ struct stm32_ed_s *prev;
+ uint32_t regval;
+
+ /* Find the ED in the bulk list. NOTE: We really should never be mucking
+ * with the bulk list while BLE is set.
+ */
+
+ for (curr = (struct stm32_ed_s *)stm32_getreg(STM32_USBHOST_BULKHEADED),
+ prev = NULL;
+ curr && curr != ed;
+ prev = curr, curr = (struct stm32_ed_s *)curr->hw.nexted);
+
+ /* Hmmm.. It would be a bug if we do not find the ED in the bulk list. */
+
+ DEBUGASSERT(curr != NULL);
+
+ /* Remove the ED from the bulk list */
+
+ if (curr != NULL)
+ {
+ /* Is this ED the first on in the bulk list? */
+
+ if (prev == NULL)
+ {
+ /* Yes... set the head of the bulk list to skip over this ED */
+
+ stm32_putreg(ed->hw.nexted, STM32_USBHOST_BULKHEADED);
+
+ /* If the bulk list is now empty, then disable it */
+
+ regval = stm32_getreg(STM32_USBHOST_CTRL);
+ regval &= ~OHCI_CTRL_BLE;
+ stm32_putreg(regval, STM32_USBHOST_CTRL);
+ }
+ else
+ {
+ /* No.. set the forward link of the previous ED in the list
+ * skip over this ED.
+ */
+
+ prev->hw.nexted = ed->hw.nexted;
+ }
+ }
+
+ return OK;
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*******************************************************************************
+ * Name: stm32_getinterval
+ *
+ * Description:
+ * Convert the endpoint polling interval into a HCCA table increment
+ *
+ *******************************************************************************/
+
+#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE)
+static unsigned int stm32_getinterval(uint8_t interval)
+{
+ /* The bInterval field of the endpoint descriptor contains the polling interval
+ * for interrupt and isochronous endpoints. For other types of endpoint, this
+ * value should be ignored. bInterval is provided in units of 1MS frames.
+ */
+
+ if (interval < 3)
+ {
+ return 2;
+ }
+ else if (interval < 7)
+ {
+ return 4;
+ }
+ else if (interval < 15)
+ {
+ return 8;
+ }
+ else if (interval < 31)
+ {
+ return 16;
+ }
+ else
+ {
+ return 32;
+ }
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_setinttab
+ *
+ * Description:
+ * Set the interrupt table to the selected value using the provided interval
+ * and offset.
+ *
+ *******************************************************************************/
+
+#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE)
+static void stm32_setinttab(uint32_t value, unsigned int interval, unsigned int offset)
+{
+ unsigned int i;
+ for (i = offset; i < HCCA_INTTBL_WSIZE; i += interval)
+ {
+ HCCA->inttbl[i] = value;
+ }
+}
+#endif
+
+/*******************************************************************************
+ * Name: stm32_addinted
+ *
+ * Description:
+ * Helper function to add an ED to the HCCA interrupt table.
+ *
+ * To avoid reshuffling the table so much and to keep life simple in general,
+ * the following rules are applied:
+ *
+ * 1. IN EDs get the even entries, OUT EDs get the odd entries.
+ * 2. Add IN/OUT EDs are scheduled together at the minimum interval of all
+ * IN/OUT EDs.
+ *
+ * This has the following consequences:
+ *
+ * 1. The minimum support polling rate is 2MS, and
+ * 2. Some devices may get polled at a much higher rate than they request.
+ *
+ *******************************************************************************/
+
+static inline int stm32_addinted(struct stm32_usbhost_s *priv,
+ const FAR struct usbhost_epdesc_s *epdesc,
+ struct stm32_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_INT_DISABLE
+ unsigned int interval;
+ unsigned int offset;
+ uint32_t head;
+ uint32_t regval;
+
+ /* Disable periodic list processing. Does this take effect immediately? Or
+ * at the next SOF... need to check.
+ */
+
+ regval = stm32_getreg(STM32_USBHOST_CTRL);
+ regval &= ~OHCI_CTRL_PLE;
+ stm32_putreg(regval, STM32_USBHOST_CTRL);
+
+ /* Get the quanitized interval value associated with this ED and save it
+ * in the ED.
+ */
+
+ interval = stm32_getinterval(epdesc->interval);
+ ed->interval = interval;
+ uvdbg("interval: %d->%d\n", epdesc->interval, interval);
+
+ /* Get the offset associated with the ED direction. IN EDs get the even
+ * entries, OUT EDs get the odd entries.
+ *
+ * Get the new, minimum interval. Add IN/OUT EDs are scheduled together
+ * at the minimum interval of all IN/OUT EDs.
+ */
+
+ if (epdesc->in)
+ {
+ offset = 0;
+ if (priv->ininterval > interval)
+ {
+ priv->ininterval = interval;
+ }
+ else
+ {
+ interval = priv->ininterval;
+ }
+ }
+ else
+ {
+ offset = 1;
+ if (priv->outinterval > interval)
+ {
+ priv->outinterval = interval;
+ }
+ else
+ {
+ interval = priv->outinterval;
+ }
+ }
+ uvdbg("min interval: %d offset: %d\n", interval, offset);
+
+ /* Get the head of the first of the duplicated entries. The first offset
+ * entry is always guaranteed to contain the common ED list head.
+ */
+
+ head = HCCA->inttbl[offset];
+
+ /* Clear all current entries in the interrupt table for this direction */
+
+ stm32_setinttab(0, 2, offset);
+
+ /* Add the new ED before the old head of the periodic ED list and set the
+ * new ED as the head ED in all of the appropriate entries of the HCCA
+ * interrupt table.
+ */
+
+ ed->hw.nexted = head;
+ stm32_setinttab((uint32_t)ed, interval, offset);
+ uvdbg("head: %08x next: %08x\n", ed, head);
+
+ /* Re-enabled periodic list processing */
+
+ regval = stm32_getreg(STM32_USBHOST_CTRL);
+ regval |= OHCI_CTRL_PLE;
+ stm32_putreg(regval, STM32_USBHOST_CTRL);
+ return OK;
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*******************************************************************************
+ * Name: stm32_reminted
+ *
+ * Description:
+ * Helper function to remove an ED from the HCCA interrupt table.
+ *
+ * To avoid reshuffling the table so much and to keep life simple in general,
+ * the following rules are applied:
+ *
+ * 1. IN EDs get the even entries, OUT EDs get the odd entries.
+ * 2. Add IN/OUT EDs are scheduled together at the minimum interval of all
+ * IN/OUT EDs.
+ *
+ * This has the following consequences:
+ *
+ * 1. The minimum support polling rate is 2MS, and
+ * 2. Some devices may get polled at a much higher rate than they request.
+ *
+ *******************************************************************************/
+
+static inline int stm32_reminted(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_INT_DISABLE
+ struct stm32_ed_s *head;
+ struct stm32_ed_s *curr;
+ struct stm32_ed_s *prev;
+ unsigned int interval;
+ unsigned int offset;
+ uint32_t regval;
+
+ /* Disable periodic list processing. Does this take effect immediately? Or
+ * at the next SOF... need to check.
+ */
+
+ regval = stm32_getreg(STM32_USBHOST_CTRL);
+ regval &= ~OHCI_CTRL_PLE;
+ stm32_putreg(regval, STM32_USBHOST_CTRL);
+
+ /* Get the offset associated with the ED direction. IN EDs get the even
+ * entries, OUT EDs get the odd entries.
+ */
+
+ if ((ed->hw.ctrl & ED_CONTROL_D_MASK) == ED_CONTROL_D_IN)
+ {
+ offset = 0;
+ }
+ else
+ {
+ offset = 1;
+ }
+
+ /* Get the head of the first of the duplicated entries. The first offset
+ * entry is always guaranteed to contain the common ED list head.
+ */
+
+ head = (struct stm32_ed_s *)HCCA->inttbl[offset];
+ uvdbg("ed: %08x head: %08x next: %08x offset: %d\n",
+ ed, head, head ? head->hw.nexted : 0, offset);
+
+ /* Find the ED to be removed in the ED list */
+
+ for (curr = head, prev = NULL;
+ curr && curr != ed;
+ prev = curr, curr = (struct stm32_ed_s *)curr->hw.nexted);
+
+ /* Hmmm.. It would be a bug if we do not find the ED in the bulk list. */
+
+ DEBUGASSERT(curr != NULL);
+ if (curr != NULL)
+ {
+ /* Clear all current entries in the interrupt table for this direction */
+
+ stm32_setinttab(0, 2, offset);
+
+ /* Remove the ED from the list.. Is this ED the first on in the list? */
+
+ if (prev == NULL)
+ {
+ /* Yes... set the head of the bulk list to skip over this ED */
+
+ head = (struct stm32_ed_s *)ed->hw.nexted;
+ }
+ else
+ {
+ /* No.. set the forward link of the previous ED in the list
+ * skip over this ED.
+ */
+
+ prev->hw.nexted = ed->hw.nexted;
+ }
+ uvdbg("ed: %08x head: %08x next: %08x\n",
+ ed, head, head ? head->hw.nexted : 0);
+
+ /* Calculate the new minimum interval for this list */
+
+ interval = MAX_PERINTERVAL;
+ for (curr = head; curr; curr = (struct stm32_ed_s *)curr->hw.nexted)
+ {
+ if (curr->interval < interval)
+ {
+ interval = curr->interval;
+ }
+ }
+ uvdbg("min interval: %d offset: %d\n", interval, offset);
+
+ /* Save the new minimum interval */
+
+ if ((ed->hw.ctrl && ED_CONTROL_D_MASK) == ED_CONTROL_D_IN)
+ {
+ priv->ininterval = interval;
+ }
+ else
+ {
+ priv->outinterval = interval;
+ }
+
+ /* Set the head ED in all of the appropriate entries of the HCCA interrupt
+ * table (head might be NULL).
+ */
+
+ stm32_setinttab((uint32_t)head, interval, offset);
+ }
+
+ /* Re-enabled periodic list processing */
+
+ if (head != NULL)
+ {
+ regval = stm32_getreg(STM32_USBHOST_CTRL);
+ regval |= OHCI_CTRL_PLE;
+ stm32_putreg(regval, STM32_USBHOST_CTRL);
+ }
+
+ return OK;
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*******************************************************************************
+ * Name: stm32_addisoced
+ *
+ * Description:
+ * Helper functions to add an ED to the periodic table.
+ *
+ *******************************************************************************/
+
+static inline int stm32_addisoced(struct stm32_usbhost_s *priv,
+ const FAR struct usbhost_epdesc_s *epdesc,
+ struct stm32_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_ISOC_DISABLE
+# warning "Isochronous endpoints not yet supported"
+#endif
+ return -ENOSYS;
+
+}
+
+/*******************************************************************************
+ * Name: stm32_remisoced
+ *
+ * Description:
+ * Helper functions to remove an ED from the periodic table.
+ *
+ *******************************************************************************/
+
+static inline int stm32_remisoced(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed)
+{
+#ifndef CONFIG_USBHOST_ISOC_DISABLE
+# warning "Isochronous endpoints not yet supported"
+#endif
+ return -ENOSYS;
+}
+
+/*******************************************************************************
+ * Name: stm32_enqueuetd
+ *
+ * Description:
+ * Enqueue a transfer descriptor. Notice that this function only supports
+ * queue on TD per ED.
+ *
+ *******************************************************************************/
+
+static int stm32_enqueuetd(struct stm32_usbhost_s *priv,
+ struct stm32_ed_s *ed, uint32_t dirpid,
+ uint32_t toggle, volatile uint8_t *buffer, size_t buflen)
+{
+ struct stm32_gtd_s *td;
+ int ret = -ENOMEM;
+
+ /* Allocate a TD from the free list */
+
+ td = stm32_tdalloc();
+ if (td != NULL)
+ {
+ /* Initialize the allocated TD and link it before the common tail TD. */
+
+ td->hw.ctrl = (GTD_STATUS_R | dirpid | TD_DELAY(0) | toggle | GTD_STATUS_CC_MASK);
+ TDTAIL->hw.ctrl = 0;
+ td->hw.cbp = (uint32_t)buffer;
+ TDTAIL->hw.cbp = 0;
+ td->hw.nexttd = (uint32_t)TDTAIL;
+ TDTAIL->hw.nexttd = 0;
+ td->hw.be = (uint32_t)(buffer + (buflen - 1));
+ TDTAIL->hw.be = 0;
+
+ /* Configure driver-only fields in the extended TD structure */
+
+ td->ed = ed;
+
+ /* Link the td to the head of the ED's TD list */
+
+ ed->hw.headp = (uint32_t)td | ((ed->hw.headp) & ED_HEADP_C);
+ ed->hw.tailp = (uint32_t)TDTAIL;
+
+ ret = OK;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_wdhwait
+ *
+ * Description:
+ * Set the request for the Writeback Done Head event well BEFORE enabling the
+ * transfer (as soon as we are absolutely committed to the to avoid transfer).
+ * We do this to minimize race conditions. This logic would have to be expanded
+ * if we want to have more than one packet in flight at a time!
+ *
+ *******************************************************************************/
+
+static int stm32_wdhwait(struct stm32_usbhost_s *priv, struct stm32_ed_s *ed)
+{
+ irqstate_t flags = irqsave();
+ int ret = -ENODEV;
+
+ /* Is the device still connected? */
+
+ if (priv->connected)
+ {
+ /* Yes.. then set wdhwait to indicate that we expect to be informed when
+ * either (1) the device is disconnected, or (2) the transfer completed.
+ */
+
+ ed->wdhwait = true;
+ ret = OK;
+ }
+
+ irqrestore(flags);
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_ctrltd
+ *
+ * Description:
+ * Process a IN or OUT request on the control endpoint. This function
+ * will enqueue the request and wait for it to complete. Only one transfer
+ * may be queued; Neither these methods nor the transfer() method can be
+ * called again until the control transfer functions returns.
+ *
+ * These are blocking methods; these functions will not return until the
+ * control transfer has completed.
+ *
+ *******************************************************************************/
+
+static int stm32_ctrltd(struct stm32_usbhost_s *priv, uint32_t dirpid,
+ uint8_t *buffer, size_t buflen)
+{
+ uint32_t toggle;
+ uint32_t regval;
+ int ret;
+
+ /* Set the request for the Writeback Done Head event well BEFORE enabling the
+ * transfer.
+ */
+
+ ret = stm32_wdhwait(priv, EDCTRL);
+ if (ret != OK)
+ {
+ udbg("ERROR: Device disconnected\n");
+ return ret;
+ }
+
+ /* Configure the toggle field in the TD */
+
+ if (dirpid == GTD_STATUS_DP_SETUP)
+ {
+ toggle = GTD_STATUS_T_DATA0;
+ }
+ else
+ {
+ toggle = GTD_STATUS_T_DATA1;
+ }
+
+ /* Then enqueue the transfer */
+
+ EDCTRL->tdstatus = TD_CC_NOERROR;
+ ret = stm32_enqueuetd(priv, EDCTRL, dirpid, toggle, buffer, buflen);
+ if (ret == OK)
+ {
+ /* Set ControlListFilled. This bit is used to indicate whether there are
+ * TDs on the Control list.
+ */
+
+ regval = stm32_getreg(STM32_USBHOST_CMDST);
+ regval |= OHCI_CMDST_CLF;
+ stm32_putreg(regval, STM32_USBHOST_CMDST);
+
+ /* Wait for the Writeback Done Head interrupt */
+
+ stm32_takesem(&EDCTRL->wdhsem);
+
+ /* Check the TD completion status bits */
+
+ if (EDCTRL->tdstatus == TD_CC_NOERROR)
+ {
+ ret = OK;
+ }
+ else
+ {
+ uvdbg("Bad TD completion status: %d\n", EDCTRL->tdstatus);
+ ret = -EIO;
+ }
+ }
+
+ /* Make sure that there is no outstanding request on this endpoint */
+
+ EDCTRL->wdhwait = false;
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_usbinterrupt
+ *
+ * Description:
+ * USB interrupt handler
+ *
+ *******************************************************************************/
+
+static int stm32_usbinterrupt(int irq, FAR void *context)
+{
+ struct stm32_usbhost_s *priv = &g_usbhost;
+ uint32_t intst;
+ uint32_t pending;
+ uint32_t regval;
+
+ /* Read Interrupt Status and mask out interrupts that are not enabled. */
+
+ intst = stm32_getreg(STM32_USBHOST_INTST);
+ regval = stm32_getreg(STM32_USBHOST_INTEN);
+ ullvdbg("INST: %08x INTEN: %08x\n", intst, regval);
+
+ pending = intst & regval;
+ if (pending != 0)
+ {
+ /* Root hub status change interrupt */
+
+ if ((pending & OHCI_INT_RHSC) != 0)
+ {
+ uint32_t rhportst1 = stm32_getreg(STM32_USBHOST_RHPORTST1);
+ ullvdbg("Root Hub Status Change, RHPORTST1: %08x\n", rhportst1);
+
+ if ((rhportst1 & OHCI_RHPORTST_CSC) != 0)
+ {
+ uint32_t rhstatus = stm32_getreg(STM32_USBHOST_RHSTATUS);
+ ullvdbg("Connect Status Change, RHSTATUS: %08x\n", rhstatus);
+
+ /* If DRWE is set, Connect Status Change indicates a remote wake-up event */
+
+ if (rhstatus & OHCI_RHSTATUS_DRWE)
+ {
+ ullvdbg("DRWE: Remote wake-up\n");
+ }
+
+ /* Otherwise... Not a remote wake-up event */
+
+ else
+ {
+ /* Check current connect status */
+
+ if ((rhportst1 & OHCI_RHPORTST_CCS) != 0)
+ {
+ /* Connected ... Did we just become connected? */
+
+ if (!priv->connected)
+ {
+ /* Yes.. connected. */
+
+ ullvdbg("Connected\n");
+ priv->connected = true;
+
+ /* Notify any waiters */
+
+ if (priv->rhswait)
+ {
+ stm32_givesem(&priv->rhssem);
+ priv->rhswait = false;
+ }
+ }
+ else
+ {
+ ulldbg("Spurious status change (connected)\n");
+ }
+
+ /* The LSDA (Low speed device attached) bit is valid
+ * when CCS == 1.
+ */
+
+ priv->lowspeed = (rhportst1 & OHCI_RHPORTST_LSDA) != 0;
+ ullvdbg("Speed:%s\n", priv->lowspeed ? "LOW" : "FULL");
+ }
+
+ /* Check if we are now disconnected */
+
+ else if (priv->connected)
+ {
+ /* Yes.. disconnect the device */
+
+ ullvdbg("Disconnected\n");
+ priv->connected = false;
+ priv->lowspeed = false;
+
+ /* Are we bound to a class instance? */
+
+ if (priv->class)
+ {
+ /* Yes.. Disconnect the class */
+
+ CLASS_DISCONNECTED(priv->class);
+ priv->class = NULL;
+ }
+
+ /* Notify any waiters for the Root Hub Status change event */
+
+ if (priv->rhswait)
+ {
+ stm32_givesem(&priv->rhssem);
+ priv->rhswait = false;
+ }
+ }
+ else
+ {
+ ulldbg("Spurious status change (disconnected)\n");
+ }
+ }
+
+ /* Clear the status change interrupt */
+
+ stm32_putreg(OHCI_RHPORTST_CSC, STM32_USBHOST_RHPORTST1);
+ }
+
+ /* Check for port reset status change */
+
+ if ((rhportst1 & OHCI_RHPORTST_PRSC) != 0)
+ {
+ /* Release the RH port from reset */
+
+ stm32_putreg(OHCI_RHPORTST_PRSC, STM32_USBHOST_RHPORTST1);
+ }
+ }
+
+ /* Writeback Done Head interrupt */
+
+ if ((pending & OHCI_INT_WDH) != 0)
+ {
+ struct stm32_gtd_s *td;
+ struct stm32_gtd_s *next;
+
+ /* The host controller just wrote the list of finished TDs into the HCCA
+ * done head. This may include multiple packets that were transferred
+ * in the preceding frame.
+ *
+ * Remove the TD(s) from the Writeback Done Head in the HCCA and return
+ * them to the free list. Note that this is safe because the hardware
+ * will not modify the writeback done head again until the WDH bit is
+ * cleared in the interrupt status register.
+ */
+
+ td = (struct stm32_gtd_s *)HCCA->donehead;
+ HCCA->donehead = 0;
+
+ /* Process each TD in the write done list */
+
+ for (; td; td = next)
+ {
+ /* Get the ED in which this TD was enqueued */
+
+ struct stm32_ed_s *ed = td->ed;
+ DEBUGASSERT(ed != NULL);
+
+ /* Save the condition code from the (single) TD status/control
+ * word.
+ */
+
+ ed->tdstatus = (td->hw.ctrl & GTD_STATUS_CC_MASK) >> GTD_STATUS_CC_SHIFT;
+
+#ifdef CONFIG_DEBUG_USB
+ if (ed->tdstatus != TD_CC_NOERROR)
+ {
+ /* The transfer failed for some reason... dump some diagnostic info. */
+
+ ulldbg("ERROR: ED xfrtype:%d TD CTRL:%08x/CC:%d RHPORTST1:%08x\n",
+ ed->xfrtype, td->hw.ctrl, ed->tdstatus,
+ stm32_getreg(STM32_USBHOST_RHPORTST1));
+ }
+#endif
+
+ /* Return the TD to the free list */
+
+ next = (struct stm32_gtd_s *)td->hw.nexttd;
+ stm32_tdfree(td);
+
+ /* And wake up the thread waiting for the WDH event */
+
+ if (ed->wdhwait)
+ {
+ stm32_givesem(&ed->wdhsem);
+ ed->wdhwait = false;
+ }
+ }
+ }
+
+#ifdef CONFIG_DEBUG_USB
+ if ((pending & STM32_DEBUG_INTS) != 0)
+ {
+ ulldbg("ERROR: Unhandled interrupts INTST:%08x\n", intst);
+ }
+#endif
+
+ /* Clear interrupt status register */
+
+ stm32_putreg(intst, STM32_USBHOST_INTST);
+ }
+
+ return OK;
+}
+
+/*******************************************************************************
+ * USB Host Controller Operations
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: stm32_wait
+ *
+ * Description:
+ * Wait for a device to be connected or disconneced.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * connected - TRUE: Wait for device to be connected; FALSE: wait for device
+ * to be disconnected
+ *
+ * Returned Values:
+ * Zero (OK) is returned when a device in connected. This function will not
+ * return until either (1) a device is connected or (2) some failure occurs.
+ * On a failure, a negated errno value is returned indicating the nature of
+ * the failure
+ *
+ * Assumptions:
+ * - Called from a single thread so no mutual exclusion is required.
+ * - Never called from an interrupt handler.
+ *
+ *******************************************************************************/
+
+static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ irqstate_t flags;
+
+ /* Are we already connected? */
+
+ flags = irqsave();
+ while (priv->connected == connected)
+ {
+ /* No... wait for the connection/disconnection */
+
+ priv->rhswait = true;
+ stm32_takesem(&priv->rhssem);
+ }
+ irqrestore(flags);
+
+ udbg("Connected:%s\n", priv->connected ? "YES" : "NO");
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: stm32_enumerate
+ *
+ * Description:
+ * Enumerate the connected device. As part of this enumeration process,
+ * the driver will (1) get the device's configuration descriptor, (2)
+ * extract the class ID info from the configuration descriptor, (3) call
+ * usbhost_findclass() to find the class that supports this device, (4)
+ * call the create() method on the struct usbhost_registry_s interface
+ * to get a class instance, and finally (5) call the configdesc() method
+ * of the struct usbhost_class_s interface. After that, the class is in
+ * charge of the sequence of operations.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * - Only a single class bound to a single device is supported.
+ * - Called from a single thread so no mutual exclusion is required.
+ * - Never called from an interrupt handler.
+ *
+ *******************************************************************************/
+
+static int stm32_enumerate(FAR struct usbhost_driver_s *drvr)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+
+ /* Are we connected to a device? The caller should have called the wait()
+ * method first to be assured that a device is connected.
+ */
+
+ while (!priv->connected)
+ {
+ /* No, return an error */
+
+ udbg("Not connected\n");
+ return -ENODEV;
+ }
+
+ /* USB 2.0 spec says at least 50ms delay before port reset */
+
+ up_mdelay(100);
+
+ /* Put RH port 1 in reset (the STM32 supports only a single downstream port) */
+
+ stm32_putreg(OHCI_RHPORTST_PRS, STM32_USBHOST_RHPORTST1);
+
+ /* Wait for the port reset to complete */
+
+ while ((stm32_getreg(STM32_USBHOST_RHPORTST1) & OHCI_RHPORTST_PRS) != 0);
+
+ /* Release RH port 1 from reset and wait a bit */
+
+ stm32_putreg(OHCI_RHPORTST_PRSC, STM32_USBHOST_RHPORTST1);
+ up_mdelay(200);
+
+ /* Let the common usbhost_enumerate do all of the real work. Note that the
+ * FunctionAddress (USB address) is hardcoded to one.
+ */
+
+ uvdbg("Enumerate the device\n");
+ return usbhost_enumerate(drvr, 1, &priv->class);
+}
+
+/************************************************************************************
+ * Name: stm32_ep0configure
+ *
+ * Description:
+ * Configure endpoint 0. This method is normally used internally by the
+ * enumerate() method but is made available at the interface to support
+ * an external implementation of the enumeration logic.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * funcaddr - The USB address of the function containing the endpoint that EP0
+ * controls
+ * maxpacketsize - The maximum number of bytes that can be sent to or
+ * received from the endpoint in a single data packet
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * This function will *not* be called from an interrupt handler.
+ *
+ ************************************************************************************/
+
+static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
+ uint16_t maxpacketsize)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+
+ DEBUGASSERT(drvr && funcaddr < 128 && maxpacketsize < 2048);
+
+ /* We must have exclusive access to EP0 and the control list */
+
+ stm32_takesem(&priv->exclsem);
+
+ /* Set the EP0 ED control word */
+
+ EDCTRL->hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT |
+ (uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT;
+
+ if (priv->lowspeed)
+ {
+ EDCTRL->hw.ctrl |= ED_CONTROL_S;
+ }
+
+ /* Set the transfer type to control */
+
+ EDCTRL->xfrtype = USB_EP_ATTR_XFER_CONTROL;
+ stm32_givesem(&priv->exclsem);
+
+ uvdbg("EP0 CTRL:%08x\n", EDCTRL->hw.ctrl);
+ return OK;
+}
+
+/************************************************************************************
+ * Name: stm32_epalloc
+ *
+ * Description:
+ * Allocate and configure one endpoint.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * epdesc - Describes the endpoint to be allocated.
+ * ep - A memory location provided by the caller in which to receive the
+ * allocated endpoint desciptor.
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * This function will *not* be called from an interrupt handler.
+ *
+ ************************************************************************************/
+
+static int stm32_epalloc(FAR struct usbhost_driver_s *drvr,
+ const FAR struct usbhost_epdesc_s *epdesc, usbhost_ep_t *ep)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ struct stm32_ed_s *ed;
+ int ret = -ENOMEM;
+
+ /* Sanity check. NOTE that this method should only be called if a device is
+ * connected (because we need a valid low speed indication).
+ */
+
+ DEBUGASSERT(priv && epdesc && ep && priv->connected);
+
+ /* We must have exclusive access to the ED pool, the bulk list, the periodic list
+ * and the interrupt table.
+ */
+
+ stm32_takesem(&priv->exclsem);
+
+ /* Take the next ED from the beginning of the free list */
+
+ ed = (struct stm32_ed_s *)g_edfree;
+ if (ed)
+ {
+ /* Remove the ED from the freelist */
+
+ g_edfree = ((struct stm32_list_s*)ed)->flink;
+
+ /* Configure the endpoint descriptor. */
+
+ memset((void*)ed, 0, sizeof(struct stm32_ed_s));
+ ed->hw.ctrl = (uint32_t)(epdesc->funcaddr) << ED_CONTROL_FA_SHIFT |
+ (uint32_t)(epdesc->addr) << ED_CONTROL_EN_SHIFT |
+ (uint32_t)(epdesc->mxpacketsize) << ED_CONTROL_MPS_SHIFT;
+
+ /* Get the direction of the endpoint */
+
+ if (epdesc->in)
+ {
+ ed->hw.ctrl |= ED_CONTROL_D_IN;
+ }
+ else
+ {
+ ed->hw.ctrl |= ED_CONTROL_D_OUT;
+ }
+
+ /* Check for a low-speed device */
+
+ if (priv->lowspeed)
+ {
+ ed->hw.ctrl |= ED_CONTROL_S;
+ }
+
+ /* Set the transfer type */
+
+ ed->xfrtype = epdesc->xfrtype;
+
+ /* Special Case isochronous transfer types */
+
+#if 0 /* Isochronous transfers not yet supported */
+ if (ed->xfrtype == USB_EP_ATTR_XFER_ISOC)
+ {
+ ed->hw.ctrl |= ED_CONTROL_F;
+ }
+#endif
+ uvdbg("EP%d CTRL:%08x\n", epdesc->addr, ed->hw.ctrl);
+
+ /* Initialize the semaphore that is used to wait for the endpoint
+ * WDH event.
+ */
+
+ sem_init(&ed->wdhsem, 0, 0);
+
+ /* Link the common tail TD to the ED's TD list */
+
+ ed->hw.headp = (uint32_t)TDTAIL;
+ ed->hw.tailp = (uint32_t)TDTAIL;
+
+ /* Now add the endpoint descriptor to the appropriate list */
+
+ switch (ed->xfrtype)
+ {
+ case USB_EP_ATTR_XFER_BULK:
+ ret = stm32_addbulked(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_INT:
+ ret = stm32_addinted(priv, epdesc, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_ISOC:
+ ret = stm32_addisoced(priv, epdesc, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_CONTROL:
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ /* Was the ED successfully added? */
+
+ if (ret != OK)
+ {
+ /* No.. destroy it and report the error */
+
+ udbg("ERROR: Failed to queue ED for transfer type: %d\n", ed->xfrtype);
+ sem_destroy(&ed->wdhsem);
+ stm32_edfree(ed);
+ }
+ else
+ {
+ /* Yes.. return an opaque reference to the ED */
+
+ *ep = (usbhost_ep_t)ed;
+ }
+ }
+
+ stm32_givesem(&priv->exclsem);
+ return ret;
+}
+
+/************************************************************************************
+ * Name: stm32_epfree
+ *
+ * Description:
+ * Free and endpoint previously allocated by DRVR_EPALLOC.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * ep - The endpint to be freed.
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * This function will *not* be called from an interrupt handler.
+ *
+ ************************************************************************************/
+
+static int stm32_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ struct stm32_ed_s *ed = (struct stm32_ed_s *)ep;
+ int ret;
+
+ /* There should not be any pending, real TDs linked to this ED */
+
+ DEBUGASSERT(ed && (ed->hw.headp & ED_HEADP_ADDR_MASK) == STM32_TDTAIL_ADDR);
+
+ /* We must have exclusive access to the ED pool, the bulk list, the periodic list
+ * and the interrupt table.
+ */
+
+ stm32_takesem(&priv->exclsem);
+
+ /* Remove the ED to the correct list depending on the trasfer type */
+
+ switch (ed->xfrtype)
+ {
+ case USB_EP_ATTR_XFER_BULK:
+ ret = stm32_rembulked(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_INT:
+ ret = stm32_reminted(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_ISOC:
+ ret = stm32_remisoced(priv, ed);
+ break;
+
+ case USB_EP_ATTR_XFER_CONTROL:
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ /* Destroy the semaphore */
+
+ sem_destroy(&ed->wdhsem);
+
+ /* Put the ED back into the free list */
+
+ stm32_edfree(ed);
+ stm32_givesem(&priv->exclsem);
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_alloc
+ *
+ * Description:
+ * Some hardware supports special memory in which request and descriptor data can
+ * be accessed more efficiently. This method provides a mechanism to allocate
+ * the request/descriptor memory. If the underlying hardware does not support
+ * such "special" memory, this functions may simply map to malloc.
+ *
+ * This interface was optimized under a particular assumption. It was assumed
+ * that the driver maintains a pool of small, pre-allocated buffers for descriptor
+ * traffic. NOTE that size is not an input, but an output: The size of the
+ * pre-allocated buffer is returned.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * buffer - The address of a memory location provided by the caller in which to
+ * return the allocated buffer memory address.
+ * maxlen - The address of a memory location provided by the caller in which to
+ * return the maximum size of the allocated buffer memory.
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * - Called from a single thread so no mutual exclusion is required.
+ * - Never called from an interrupt handler.
+ *
+ *******************************************************************************/
+
+static int stm32_alloc(FAR struct usbhost_driver_s *drvr,
+ FAR uint8_t **buffer, FAR size_t *maxlen)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ DEBUGASSERT(priv && buffer && maxlen);
+ int ret = -ENOMEM;
+
+ /* We must have exclusive access to the transfer buffer pool */
+
+ stm32_takesem(&priv->exclsem);
+
+ *buffer = stm32_tballoc();
+ if (*buffer)
+ {
+ *maxlen = CONFIG_USBHOST_TDBUFSIZE;
+ ret = OK;
+ }
+
+ stm32_givesem(&priv->exclsem);
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_free
+ *
+ * Description:
+ * Some hardware supports special memory in which request and descriptor data can
+ * be accessed more efficiently. This method provides a mechanism to free that
+ * request/descriptor memory. If the underlying hardware does not support
+ * such "special" memory, this functions may simply map to free().
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * buffer - The address of the allocated buffer memory to be freed.
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * - Never called from an interrupt handler.
+ *
+ *******************************************************************************/
+
+static int stm32_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ DEBUGASSERT(buffer);
+
+ /* We must have exclusive access to the transfer buffer pool */
+
+ stm32_takesem(&priv->exclsem);
+ stm32_tbfree(buffer);
+ stm32_givesem(&priv->exclsem);
+ return OK;
+}
+
+/************************************************************************************
+ * Name: stm32_ioalloc
+ *
+ * Description:
+ * Some hardware supports special memory in which larger IO buffers can
+ * be accessed more efficiently. This method provides a mechanism to allocate
+ * the request/descriptor memory. If the underlying hardware does not support
+ * such "special" memory, this functions may simply map to malloc.
+ *
+ * This interface differs from DRVR_ALLOC in that the buffers are variable-sized.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * buffer - The address of a memory location provided by the caller in which to
+ * return the allocated buffer memory address.
+ * buflen - The size of the buffer required.
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * This function will *not* be called from an interrupt handler.
+ *
+ ************************************************************************************/
+
+static int stm32_ioalloc(FAR struct usbhost_driver_s *drvr,
+ FAR uint8_t **buffer, size_t buflen)
+{
+ DEBUGASSERT(drvr && buffer);
+
+#if STM32_IOBUFFERS > 0
+ if (buflen <= CONFIG_USBHOST_IOBUFSIZE)
+ {
+ FAR uint8_t *alloc = stm32_allocio();
+ if (alloc)
+ {
+ *buffer = alloc;
+ return OK;
+ }
+ }
+ return -ENOMEM;
+#else
+ return -ENOSYS;
+#endif
+}
+
+/************************************************************************************
+ * Name: stm32_iofree
+ *
+ * Description:
+ * Some hardware supports special memory in which IO data can be accessed more
+ * efficiently. This method provides a mechanism to free that IO buffer
+ * memory. If the underlying hardware does not support such "special" memory,
+ * this functions may simply map to free().
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * buffer - The address of the allocated buffer memory to be freed.
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * This function will *not* be called from an interrupt handler.
+ *
+ ************************************************************************************/
+
+static int stm32_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
+{
+ DEBUGASSERT(drvr && buffer);
+
+#if STM32_IOBUFFERS > 0
+ stm32_freeio(buffer);
+ return OK;
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*******************************************************************************
+ * Name: stm32_ctrlin and stm32_ctrlout
+ *
+ * Description:
+ * Process a IN or OUT request on the control endpoint. These methods
+ * will enqueue the request and wait for it to complete. Only one transfer may be
+ * queued; Neither these methods nor the transfer() method can be called again
+ * until the control transfer functions returns.
+ *
+ * These are blocking methods; these functions will not return until the
+ * control transfer has completed.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * req - Describes the request to be sent. This request must lie in memory
+ * created by DRVR_ALLOC.
+ * buffer - A buffer used for sending the request and for returning any
+ * responses. This buffer must be large enough to hold the length value
+ * in the request description. buffer must have been allocated using DRVR_ALLOC
+ *
+ * NOTE: On an IN transaction, req and buffer may refer to the same allocated
+ * memory.
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * - Only a single class bound to a single device is supported.
+ * - Called from a single thread so no mutual exclusion is required.
+ * - Never called from an interrupt handler.
+ *
+ *******************************************************************************/
+
+static int stm32_ctrlin(FAR struct usbhost_driver_s *drvr,
+ FAR const struct usb_ctrlreq_s *req,
+ FAR uint8_t *buffer)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ uint16_t len;
+ int ret;
+
+ DEBUGASSERT(drvr && req);
+ uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n",
+ req->type, req->req, req->value[1], req->value[0],
+ req->index[1], req->index[0], req->len[1], req->len[0]);
+
+ /* We must have exclusive access to EP0 and the control list */
+
+ stm32_takesem(&priv->exclsem);
+
+ len = stm32_getle16(req->len);
+ ret = stm32_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
+ if (ret == OK)
+ {
+ if (len)
+ {
+ ret = stm32_ctrltd(priv, GTD_STATUS_DP_IN, buffer, len);
+ }
+
+ if (ret == OK)
+ {
+ ret = stm32_ctrltd(priv, GTD_STATUS_DP_OUT, NULL, 0);
+ }
+ }
+
+ stm32_givesem(&priv->exclsem);
+ return ret;
+}
+
+static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr,
+ FAR const struct usb_ctrlreq_s *req,
+ FAR const uint8_t *buffer)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ uint16_t len;
+ int ret;
+
+ DEBUGASSERT(drvr && req);
+ uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n",
+ req->type, req->req, req->value[1], req->value[0],
+ req->index[1], req->index[0], req->len[1], req->len[0]);
+
+ /* We must have exclusive access to EP0 and the control list */
+
+ stm32_takesem(&priv->exclsem);
+
+ len = stm32_getle16(req->len);
+ ret = stm32_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
+ if (ret == OK)
+ {
+ if (len)
+ {
+ ret = stm32_ctrltd(priv, GTD_STATUS_DP_OUT, (uint8_t*)buffer, len);
+ }
+
+ if (ret == OK)
+ {
+ ret = stm32_ctrltd(priv, GTD_STATUS_DP_IN, NULL, 0);
+ }
+ }
+
+ stm32_givesem(&priv->exclsem);
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_transfer
+ *
+ * Description:
+ * Process a request to handle a transfer descriptor. This method will
+ * enqueue the transfer request and return immediately. Only one transfer may be
+ * queued; Neither this method nor the ctrlin or ctrlout methods can be called
+ * again until this function returns.
+ *
+ * This is a blocking method; this functions will not return until the
+ * transfer has completed.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ * ep - The IN or OUT endpoint descriptor for the device endpoint on which to
+ * perform the transfer.
+ * buffer - A buffer containing the data to be sent (OUT endpoint) or received
+ * (IN endpoint). buffer must have been allocated using DRVR_ALLOC
+ * buflen - The length of the data to be sent or received.
+ *
+ * Returned Values:
+ * On success, zero (OK) is returned. On a failure, a negated errno value is
+ * returned indicating the nature of the failure
+ *
+ * Assumptions:
+ * - Only a single class bound to a single device is supported.
+ * - Called from a single thread so no mutual exclusion is required.
+ * - Never called from an interrupt handler.
+ *
+ *******************************************************************************/
+
+static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
+ FAR uint8_t *buffer, size_t buflen)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ struct stm32_ed_s *ed = (struct stm32_ed_s *)ep;
+ uint32_t dirpid;
+ uint32_t regval;
+#if STM32_IOBUFFERS > 0
+ uint8_t *origbuf = NULL;
+#endif
+ bool in;
+ int ret;
+
+ DEBUGASSERT(priv && ed && buffer && buflen > 0);
+
+ in = (ed->hw.ctrl & ED_CONTROL_D_MASK) == ED_CONTROL_D_IN;
+ uvdbg("EP%d %s toggle:%d maxpacket:%d buflen:%d\n",
+ (ed->hw.ctrl & ED_CONTROL_EN_MASK) >> ED_CONTROL_EN_SHIFT,
+ in ? "IN" : "OUT",
+ (ed->hw.headp & ED_HEADP_C) != 0 ? 1 : 0,
+ (ed->hw.ctrl & ED_CONTROL_MPS_MASK) >> ED_CONTROL_MPS_SHIFT,
+ buflen);
+
+ /* We must have exclusive access to the endpoint, the TD pool, the I/O buffer
+ * pool, the bulk and interrupt lists, and the HCCA interrupt table.
+ */
+
+ stm32_takesem(&priv->exclsem);
+
+ /* Allocate an IO buffer if the user buffer does not lie in AHB SRAM */
+
+#if STM32_IOBUFFERS > 0
+ if ((uintptr_t)buffer < STM32_SRAM_BANK0 ||
+ (uintptr_t)buffer >= (STM32_SRAM_BANK0 + STM32_BANK0_SIZE + STM32_BANK1_SIZE))
+ {
+ /* Will the transfer fit in an IO buffer? */
+
+ if (buflen > CONFIG_USBHOST_IOBUFSIZE)
+ {
+ uvdbg("buflen (%d) > IO buffer size (%d)\n",
+ buflen, CONFIG_USBHOST_IOBUFSIZE);
+ ret = -ENOMEM;
+ goto errout;
+ }
+
+ /* Allocate an IO buffer in AHB SRAM */
+
+ origbuf = buffer;
+ buffer = stm32_allocio();
+ if (!buffer)
+ {
+ uvdbg("IO buffer allocation failed\n");
+ ret = -ENOMEM;
+ goto errout;
+ }
+
+ /* If this is an OUT transaction, copy the user data into the AHB
+ * SRAM IO buffer. Sad... so inefficient. But without exposing
+ * the AHB SRAM to the final, end-user client I don't know of any
+ * way around this copy.
+ */
+
+ if (!in)
+ {
+ memcpy(buffer, origbuf, buflen);
+ }
+ }
+#endif
+
+ /* Set the request for the Writeback Done Head event well BEFORE enabling the
+ * transfer.
+ */
+
+ ret = stm32_wdhwait(priv, ed);
+ if (ret != OK)
+ {
+ udbg("ERROR: Device disconnected\n");
+ goto errout;
+ }
+
+ /* Get the direction of the endpoint */
+
+ if (in)
+ {
+ dirpid = GTD_STATUS_DP_IN;
+ }
+ else
+ {
+ dirpid = GTD_STATUS_DP_OUT;
+ }
+
+ /* Then enqueue the transfer */
+
+ ed->tdstatus = TD_CC_NOERROR;
+ ret = stm32_enqueuetd(priv, ed, dirpid, GTD_STATUS_T_TOGGLE, buffer, buflen);
+ if (ret == OK)
+ {
+ /* BulkListFilled. This bit is used to indicate whether there are any
+ * TDs on the Bulk list.
+ */
+
+ regval = stm32_getreg(STM32_USBHOST_CMDST);
+ regval |= OHCI_CMDST_BLF;
+ stm32_putreg(regval, STM32_USBHOST_CMDST);
+
+ /* Wait for the Writeback Done Head interrupt */
+
+ stm32_takesem(&ed->wdhsem);
+
+ /* Check the TD completion status bits */
+
+ if (ed->tdstatus == TD_CC_NOERROR)
+ {
+ ret = OK;
+ }
+ else
+ {
+ uvdbg("Bad TD completion status: %d\n", ed->tdstatus);
+ ret = -EIO;
+ }
+ }
+
+errout:
+ /* Make sure that there is no outstanding request on this endpoint */
+
+ ed->wdhwait = false;
+
+ /* Free any temporary IO buffers */
+
+#if STM32_IOBUFFERS > 0
+ if (buffer && origbuf)
+ {
+ /* If this is an IN transaction, get the user data from the AHB
+ * SRAM IO buffer. Sad... so inefficient. But without exposing
+ * the AHB SRAM to the final, end-user client I don't know of any
+ * way around this copy.
+ */
+
+ if (in && ret == OK)
+ {
+ memcpy(origbuf, buffer, buflen);
+ }
+
+ /* Then free the temporary I/O buffer */
+
+ stm32_freeio(buffer);
+ }
+#endif
+
+ stm32_givesem(&priv->exclsem);
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: stm32_disconnect
+ *
+ * Description:
+ * Called by the class when an error occurs and driver has been disconnected.
+ * The USB host driver should discard the handle to the class instance (it is
+ * stale) and not attempt any further interaction with the class driver instance
+ * (until a new instance is received from the create() method). The driver
+ * should not called the class' disconnected() method.
+ *
+ * Input Parameters:
+ * drvr - The USB host driver instance obtained as a parameter from the call to
+ * the class create() method.
+ *
+ * Returned Values:
+ * None
+ *
+ * Assumptions:
+ * - Only a single class bound to a single device is supported.
+ * - Never called from an interrupt handler.
+ *
+ *******************************************************************************/
+
+static void stm32_disconnect(FAR struct usbhost_driver_s *drvr)
+{
+ struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
+ priv->class = NULL;
+}
+
+/*******************************************************************************
+ * Initialization
+ *******************************************************************************/
+/*******************************************************************************
+ * Name: stm32_ep0init
+ *
+ * Description:
+ * Initialize ED for EP0, add it to the control ED list, and enable control
+ * transfers.
+ *
+ * Input Parameters:
+ * priv - private driver state instance.
+ *
+ * Returned Values:
+ * None
+ *
+ *******************************************************************************/
+
+static inline void stm32_ep0init(struct stm32_usbhost_s *priv)
+{
+ uint32_t regval;
+
+ /* Set up some default values */
+
+ (void)stm32_ep0configure(&priv->drvr, 1, 8);
+
+ /* Initialize the common tail TD. */
+
+ memset(TDTAIL, 0, sizeof(struct stm32_gtd_s));
+ TDTAIL->ed = EDCTRL;
+
+ /* Link the common tail TD to the ED's TD list */
+
+ memset(EDCTRL, 0, sizeof(struct stm32_ed_s));
+ EDCTRL->hw.headp = (uint32_t)TDTAIL;
+ EDCTRL->hw.tailp = (uint32_t)TDTAIL;
+
+ /* Set the head of the control list to the EP0 EDCTRL (this would have to
+ * change if we want more than on control EP queued at a time).
+ */
+
+ stm32_putreg(STM32_EDCTRL_ADDR, STM32_USBHOST_CTRLHEADED);
+
+ /* ControlListEnable. This bit is set to enable the processing of the
+ * Control list. Note: once enabled, it remains enabled and we may even
+ * complete list processing before we get the bit set. We really
+ * should never modify the control list while CLE is set.
+ */
+
+ regval = stm32_getreg(STM32_USBHOST_CTRL);
+ regval |= OHCI_CTRL_CLE;
+ stm32_putreg(regval, STM32_USBHOST_CTRL);
+}
+
+/*******************************************************************************
+ * Public Functions
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: usbhost_initialize
+ *
+ * Description:
+ * Initialize USB host device controller hardware.
+ *
+ * Input Parameters:
+ * controller -- If the device supports more than USB host controller, then
+ * this identifies which controller is being intialized. Normally, this
+ * is just zero.
+ *
+ * Returned Value:
+ * And instance of the USB host interface. The controlling task should
+ * use this interface to (1) call the wait() method to wait for a device
+ * to be connected, and (2) call the enumerate() method to bind the device
+ * to a class driver.
+ *
+ * Assumptions:
+ * - This function should called in the initialization sequence in order
+ * to initialize the USB device functionality.
+ * - Class drivers should be initialized prior to calling this function.
+ * Otherwise, there is a race condition if the device is already connected.
+ *
+ *******************************************************************************/
+
+FAR struct usbhost_driver_s *usbhost_initialize(int controller)
+{
+ struct stm32_usbhost_s *priv = &g_usbhost;
+ uint32_t regval;
+ uint8_t *buffer;
+ irqstate_t flags;
+ int i;
+
+ /* Sanity checks. NOTE: If certain OS features are enabled, it may be
+ * necessary to increase the size of STM32_ED/TD_SIZE in stm32_ohciram.h
+ */
+
+ DEBUGASSERT(controller == 0);
+ DEBUGASSERT(sizeof(struct stm32_ed_s) <= STM32_ED_SIZE);
+ DEBUGASSERT(sizeof(struct stm32_gtd_s) <= STM32_TD_SIZE);
+
+ /* Initialize the state data structure */
+
+ sem_init(&priv->rhssem, 0, 0);
+ sem_init(&priv->exclsem, 0, 1);
+
+#ifndef CONFIG_USBHOST_INT_DISABLE
+ priv->ininterval = MAX_PERINTERVAL;
+ priv->outinterval = MAX_PERINTERVAL;
+#endif
+
+ /* Enable power by setting PCUSB in the PCONP register. Disable interrupts
+ * because this register may be shared with other drivers.
+ */
+
+ flags = irqsave();
+ regval = stm32_getreg(STM32_SYSCON_PCONP);
+ regval |= SYSCON_PCONP_PCUSB;
+ stm32_putreg(regval, STM32_SYSCON_PCONP);
+ irqrestore(flags);
+
+ /* Enable clocking on USB (USB PLL clocking was initialized in very low-
+ * evel clock setup logic (see stm32_clockconfig.c)). We do still need
+ * to set up USBOTG CLKCTRL to enable clocking.
+ *
+ * NOTE: The PORTSEL clock needs to be enabled only when accessing OTGSTCTRL
+ */
+
+ stm32_putreg(STM32_CLKCTRL_ENABLES, STM32_USBOTG_CLKCTRL);
+
+ /* Then wait for the clocks to be reported as "ON" */
+
+ do
+ {
+ regval = stm32_getreg(STM32_USBOTG_CLKST);
+ }
+ while ((regval & STM32_CLKCTRL_ENABLES) != STM32_CLKCTRL_ENABLES);
+
+ /* Set the OTG status and control register. Bits 0:1 apparently mean:
+ *
+ * 00: U1=device, U2=host
+ * 01: U1=host, U2=host
+ * 10: reserved
+ * 11: U1=host, U2=device
+ *
+ * We need only select U1=host (Bit 0=1, Bit 1 is not used on STM32);
+ * NOTE: The PORTSEL clock needs to be enabled when accessing OTGSTCTRL
+ */
+
+ stm32_putreg(1, STM32_USBOTG_STCTRL);
+
+ /* Now we can turn off the PORTSEL clock */
+
+ stm32_putreg((STM32_CLKCTRL_ENABLES & ~USBOTG_CLK_PORTSELCLK), STM32_USBOTG_CLKCTRL);
+
+ /* Configure I/O pins */
+
+ usbhost_dumpgpio();
+ stm32_configgpio(GPIO_USB_DP); /* Positive differential data */
+ stm32_configgpio(GPIO_USB_DM); /* Negative differential data */
+ stm32_configgpio(GPIO_USB_UPLED); /* GoodLink LED control signal */
+ stm32_configgpio(GPIO_USB_PPWR); /* Port Power enable signal for USB port */
+ stm32_configgpio(GPIO_USB_PWRD); /* Power Status for USB port (host power switch) */
+ stm32_configgpio(GPIO_USB_OVRCR); /* USB port Over-Current status */
+ usbhost_dumpgpio();
+
+ udbg("Initializing Host Stack\n");
+
+ /* Show AHB SRAM memory map */
+
+#if 0 /* Useful if you have doubts about the layout */
+ uvdbg("AHB SRAM:\n");
+ uvdbg(" HCCA: %08x %d\n", STM32_HCCA_BASE, STM32_HCCA_SIZE);
+ uvdbg(" TDTAIL: %08x %d\n", STM32_TDTAIL_ADDR, STM32_TD_SIZE);
+ uvdbg(" EDCTRL: %08x %d\n", STM32_EDCTRL_ADDR, STM32_ED_SIZE);
+ uvdbg(" EDFREE: %08x %d\n", STM32_EDFREE_BASE, STM32_ED_SIZE);
+ uvdbg(" TDFREE: %08x %d\n", STM32_TDFREE_BASE, STM32_EDFREE_SIZE);
+ uvdbg(" TBFREE: %08x %d\n", STM32_TBFREE_BASE, STM32_TBFREE_SIZE);
+ uvdbg(" IOFREE: %08x %d\n", STM32_IOFREE_BASE, STM32_IOBUFFERS * CONFIG_USBHOST_IOBUFSIZE);
+#endif
+
+ /* Initialize all the TDs, EDs and HCCA to 0 */
+
+ memset((void*)HCCA, 0, sizeof(struct ohci_hcca_s));
+ memset((void*)TDTAIL, 0, sizeof(struct ohci_gtd_s));
+ memset((void*)EDCTRL, 0, sizeof(struct stm32_ed_s));
+ sem_init(&EDCTRL->wdhsem, 0, 0);
+
+ /* Initialize user-configurable EDs */
+
+ buffer = (uint8_t *)STM32_EDFREE_BASE;
+ for (i = 0; i < CONFIG_USBHOST_NEDS; i++)
+ {
+ /* Put the ED in a free list */
+
+ stm32_edfree((struct stm32_ed_s *)buffer);
+ buffer += STM32_ED_SIZE;
+ }
+
+ /* Initialize user-configurable TDs */
+
+ buffer = (uint8_t *)STM32_TDFREE_BASE;
+ for (i = 0; i < CONFIG_USBHOST_NTDS; i++)
+ {
+ /* Put the ED in a free list */
+
+ stm32_tdfree((struct stm32_gtd_s *)buffer);
+ buffer += STM32_TD_SIZE;
+ }
+
+ /* Initialize user-configurable request/descriptor transfer buffers */
+
+ buffer = (uint8_t *)STM32_TBFREE_BASE;
+ for (i = 0; i < CONFIG_USBHOST_TDBUFFERS; i++)
+ {
+ /* Put the TD buffer in a free list */
+
+ stm32_tbfree(buffer);
+ buffer += CONFIG_USBHOST_TDBUFSIZE;
+ }
+
+#if STM32_IOBUFFERS > 0
+ /* Initialize user-configurable IO buffers */
+
+ buffer = (uint8_t *)STM32_IOFREE_BASE;
+ for (i = 0; i < STM32_IOBUFFERS; i++)
+ {
+ /* Put the IO buffer in a free list */
+
+ stm32_freeio(buffer);
+ buffer += CONFIG_USBHOST_IOBUFSIZE;
+ }
+#endif
+
+ /* Wait 50MS then perform hardware reset */
+
+ up_mdelay(50);
+
+ stm32_putreg(0, STM32_USBHOST_CTRL); /* Hardware reset */
+ stm32_putreg(0, STM32_USBHOST_CTRLHEADED); /* Initialize control list head to Zero */
+ stm32_putreg(0, STM32_USBHOST_BULKHEADED); /* Initialize bulk list head to Zero */
+
+ /* Software reset */
+
+ stm32_putreg(OHCI_CMDST_HCR, STM32_USBHOST_CMDST);
+
+ /* Write Fm interval (FI), largest data packet counter (FSMPS), and
+ * periodic start.
+ */
+
+ stm32_putreg(DEFAULT_FMINTERVAL, STM32_USBHOST_FMINT);
+ stm32_putreg(DEFAULT_PERSTART, STM32_USBHOST_PERSTART);
+
+ /* Put HC in operational state */
+
+ regval = stm32_getreg(STM32_USBHOST_CTRL);
+ regval &= ~OHCI_CTRL_HCFS_MASK;
+ regval |= OHCI_CTRL_HCFS_OPER;
+ stm32_putreg(regval, STM32_USBHOST_CTRL);
+
+ /* Set global power in HcRhStatus */
+
+ stm32_putreg(OHCI_RHSTATUS_SGP, STM32_USBHOST_RHSTATUS);
+
+ /* Set HCCA base address */
+
+ stm32_putreg((uint32_t)HCCA, STM32_USBHOST_HCCA);
+
+ /* Set up EP0 */
+
+ stm32_ep0init(priv);
+
+ /* Clear pending interrupts */
+
+ regval = stm32_getreg(STM32_USBHOST_INTST);
+ stm32_putreg(regval, STM32_USBHOST_INTST);
+
+ /* Enable OHCI interrupts */
+
+ stm32_putreg((STM32_ALL_INTS|OHCI_INT_MIE), STM32_USBHOST_INTEN);
+
+ /* Attach USB host controller interrupt handler */
+
+ if (irq_attach(STM32_IRQ_USB, stm32_usbinterrupt) != 0)
+ {
+ udbg("Failed to attach IRQ\n");
+ return NULL;
+ }
+
+ /* Enable USB interrupts at the SYCON controller. Disable interrupts
+ * because this register may be shared with other drivers.
+ */
+
+ flags = irqsave();
+ regval = stm32_getreg(STM32_SYSCON_USBINTST);
+ regval |= SYSCON_USBINTST_ENINTS;
+ stm32_putreg(regval, STM32_SYSCON_USBINTST);
+ irqrestore(flags);
+
+ /* If there is a USB device in the slot at power up, then we will not
+ * get the status change interrupt to signal us that the device is
+ * connected. We need to set the initial connected state accordingly.
+ */
+
+ regval = stm32_getreg(STM32_USBHOST_RHPORTST1);
+ priv->connected = ((regval & OHCI_RHPORTST_CCS) != 0);
+
+ /* Enable interrupts at the interrupt controller */
+
+ up_enable_irq(STM32_IRQ_USB); /* enable USB interrupt */
+ udbg("USB host Initialized, Device connected:%s\n",
+ priv->connected ? "YES" : "NO");
+
+ return &priv->drvr;
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_usbhost.h b/nuttx/arch/arm/src/stm32/stm32_usbhost.h
new file mode 100644
index 000000000..854c32723
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_usbhost.h
@@ -0,0 +1,71 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_usbhost.h
+ *
+ * Copyright (C) 2012 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_STM32_STM32_USBHOST_H
+#define __ARCH_ARM_SRC_STM32_STM32_USBHOST_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/usb/usbhost.h>
+#include <stdint.h>
+
+#include "chip.h"
+#include "chip/stm32_otgfs.h"
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_USBHOST_H */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_vectors.S b/nuttx/arch/arm/src/stm32/stm32_vectors.S
new file mode 100644
index 000000000..b75237e40
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_vectors.S
@@ -0,0 +1,421 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32_vectors.S
+ * arch/arm/src/chip/stm32_vectors.S
+ *
+ * Copyright (C) 2009-2012 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 <arch/irq.h>
+
+#include "chip.h"
+
+/************************************************************************************
+ * Configuration
+ ************************************************************************************/
+/* Check if common ARMv7 interrupt vectoring is used (see
+ * arch/arm/src/armv7-m/up_vectors.S)
+ */
+
+#ifndef CONFIG_ARMV7M_CMNVECTOR
+
+/************************************************************************************
+ * Preprocessor Definitions
+ ************************************************************************************/
+/* Memory Map:
+ *
+ * 0x0800:0000 - Beginning of FLASH. Address of vectors (if not using bootloader)
+ * Mapped to address 0x0000:0000 at boot time.
+ * 0x0800:3000 - Address of vectors if using bootloader
+ * 0x0803:ffff - End of flash
+ * 0x2000:0000 - Start of SRAM and start of .data (_sdata)
+ * - End of .data (_edata) abd start of .bss (_sbss)
+ * - End of .bss (_ebss) and bottom of idle stack
+ * - _ebss + CONFIG_IDLETHREAD_STACKSIZE = end of idle stack, start of heap
+ * 0x2000:ffff - End of SRAM and end of heap
+ */
+
+#define IDLE_STACK (_ebss+CONFIG_IDLETHREAD_STACKSIZE-4)
+#define HEAP_BASE (_ebss+CONFIG_IDLETHREAD_STACKSIZE-4)
+
+/* The Cortex-M3 return from interrupt is unusual. We provide the following special
+ * address to the BX instruction. The particular value also forces a return to
+ * thread mode and covers state from the main stack point, the MSP (vs. the MSP).
+ */
+
+#define EXC_RETURN 0xfffffff9
+
+/************************************************************************************
+ * Global Symbols
+ ************************************************************************************/
+
+ .globl __start
+
+ .syntax unified
+ .thumb
+ .file "stm32_vectors.S"
+
+/************************************************************************************
+ * Macros
+ ************************************************************************************/
+
+/* On entry into an IRQ, the hardware automatically saves the xPSR, PC, LR, R12, R0-R3
+ * registers on the stack, then branches to an instantantiation of the following
+ * macro. This macro simply loads the IRQ number into R0, then jumps to the common
+ * IRQ handling logic.
+ */
+
+ .macro HANDLER, label, irqno
+ .thumb_func
+\label:
+ mov r0, #\irqno
+ b stm32_common
+ .endm
+
+/************************************************************************************
+ * Vectors
+ ************************************************************************************/
+
+ .section .vectors, "ax"
+ .code 16
+ .align 2
+ .globl stm32_vectors
+ .type stm32_vectors, function
+
+stm32_vectors:
+
+/* Processor Exceptions */
+
+ .word IDLE_STACK /* Vector 0: Reset stack pointer */
+ .word __start /* Vector 1: Reset vector */
+ .word stm32_nmi /* Vector 2: Non-Maskable Interrupt (NMI) */
+ .word stm32_hardfault /* Vector 3: Hard fault */
+ .word stm32_mpu /* Vector 4: Memory management (MPU) */
+ .word stm32_busfault /* Vector 5: Bus fault */
+ .word stm32_usagefault /* Vector 6: Usage fault */
+ .word stm32_reserved /* Vector 7: Reserved */
+ .word stm32_reserved /* Vector 8: Reserved */
+ .word stm32_reserved /* Vector 9: Reserved */
+ .word stm32_reserved /* Vector 10: Reserved */
+ .word stm32_svcall /* Vector 11: SVC call */
+ .word stm32_dbgmonitor /* Vector 12: Debug monitor */
+ .word stm32_reserved /* Vector 13: Reserved */
+ .word stm32_pendsv /* Vector 14: Pendable system service request */
+ .word stm32_systick /* Vector 15: System tick */
+
+/* External Interrupts */
+
+#undef VECTOR
+#define VECTOR(l,i) .word l
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "chip/chip/stm32f10xxx_vectors.h"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/chip/stm32f20xxx_vectors.h"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/chip/stm32f40xxx_vectors.h"
+#else
+# error "No vectors for STM32 chip"
+#endif
+ .size stm32_vectors, .-stm32_vectors
+
+/************************************************************************************
+ * .text
+ ************************************************************************************/
+
+ .text
+ .type handlers, function
+ .thumb_func
+handlers:
+ HANDLER stm32_reserved, STM32_IRQ_RESERVED /* Unexpected/reserved vector */
+ HANDLER stm32_nmi, STM32_IRQ_NMI /* Vector 2: Non-Maskable Interrupt (NMI) */
+ HANDLER stm32_hardfault, STM32_IRQ_HARDFAULT /* Vector 3: Hard fault */
+ HANDLER stm32_mpu, STM32_IRQ_MEMFAULT /* Vector 4: Memory management (MPU) */
+ HANDLER stm32_busfault, STM32_IRQ_BUSFAULT /* Vector 5: Bus fault */
+ HANDLER stm32_usagefault, STM32_IRQ_USAGEFAULT /* Vector 6: Usage fault */
+ HANDLER stm32_svcall, STM32_IRQ_SVCALL /* Vector 11: SVC call */
+ HANDLER stm32_dbgmonitor, STM32_IRQ_DBGMONITOR /* Vector 12: Debug Monitor */
+ HANDLER stm32_pendsv, STM32_IRQ_PENDSV /* Vector 14: Penable system service request */
+ HANDLER stm32_systick, STM32_IRQ_SYSTICK /* Vector 15: System tick */
+
+#undef VECTOR
+#define VECTOR(l,i) HANDLER l, i
+
+#if defined(CONFIG_STM32_STM32F10XX)
+# include "chip/chip/stm32f10xxx_vectors.h"
+#elif defined(CONFIG_STM32_STM32F20XX)
+# include "chip/chip/stm32f20xxx_vectors.h"
+#elif defined(CONFIG_STM32_STM32F40XX)
+# include "chip/chip/stm32f40xxx_vectors.h"
+#else
+# error "No handlers for STM32 chip"
+#endif
+
+/* Common IRQ handling logic. On entry here, the return stack is on either
+ * the PSP or the MSP and looks like the following:
+ *
+ * REG_XPSR
+ * REG_R15
+ * REG_R14
+ * REG_R12
+ * REG_R3
+ * REG_R2
+ * REG_R1
+ * MSP->REG_R0
+ *
+ * And
+ * R0 contains the IRQ number
+ * R14 Contains the EXC_RETURN value
+ * We are in handler mode and the current SP is the MSP
+ */
+
+stm32_common:
+
+ /* Complete the context save */
+
+#ifdef CONFIG_NUTTX_KERNEL
+ /* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1
+ * (handler mode) if the state is on the MSP. It can only be on the PSP if
+ * EXC_RETURN is 0xfffffffd (unprivileged thread)
+ */
+
+ adds r2, r14, #3 /* If R14=0xfffffffd, then r2 == 0 */
+ ite ne /* Next two instructions are conditional */
+ mrsne r1, msp /* R1=The main stack pointer */
+ mrseq r1, psp /* R1=The process stack pointer */
+#else
+ mrs r1, msp /* R1=The main stack pointer */
+#endif
+
+ /* r1 holds the value of the stack pointer AFTER the excption handling logic
+ * pushed the various registers onto the stack. Get r2 = the value of the
+ * stack pointer BEFORE the interrupt modified it.
+ */
+
+ mov r2, r1 /* R2=Copy of the main/process stack pointer */
+ add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
+ mrs r3, primask /* R3=Current PRIMASK setting */
+
+#ifdef CONFIG_ARCH_FPU
+ /* Skip over the block of memory reserved for floating pointer register save.
+ * Lazy FPU register saving is used. FPU registers will be saved in this
+ * block only if a context switch occurs (this means, of course, that the FPU
+ * cannot be used in interrupt processing).
+ */
+
+ sub r1, #(4*SW_FPU_REGS)
+#endif
+
+ /* Save the the remaining registers on the stack after the registers pushed
+ * by the exception handling logic. r2=SP and r3=primask, r4-r11,r14=register
+ * values.
+ */
+
+#ifdef CONFIG_NUTTX_KERNEL
+ stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP value */
+#else
+ stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
+#endif
+
+ /* Disable interrupts, select the stack to use for interrupt handling
+ * and call up_doirq to handle the interrupt
+ */
+
+ cpsid i /* Disable further interrupts */
+
+ /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt
+ * stack pointer. The way that this is done here prohibits nested interrupts!
+ * Otherwise, we will re-use the main stack for interrupt level processing.
+ */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ ldr sp, =g_intstackbase
+ str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
+ bl up_doirq /* R0=IRQ, R1=register save (msp) */
+ ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
+#else
+ mov sp, r1 /* We are using the main stack pointer */
+ bl up_doirq /* R0=IRQ, R1=register save (msp) */
+ mov r1, sp /* Recover R1=main stack pointer */
+#endif
+
+ /* On return from up_doirq, R0 will hold a pointer to register context
+ * array to use for the interrupt return. If that return value is the same
+ * as current stack pointer, then things are relatively easy.
+ */
+
+ cmp r0, r1 /* Context switch? */
+ beq 1f /* Branch if no context switch */
+
+ /* We are returning with a pending context switch.
+ *
+ * If the FPU is enabled, then we will need to restore FPU registers.
+ * This is not done in normal interrupt save/restore because the cost
+ * is prohibitive. This is only done when switching contexts. A
+ * consequence of this is that floating point operations may not be
+ * performed in interrupt handling logic.
+ *
+ * Here:
+ * r0 = Address of the register save area
+
+ * NOTE: It is a requirement that up_restorefpu() preserve the value of
+ * r0!
+ */
+
+#ifdef CONFIG_ARCH_FPU
+ bl up_restorefpu /* Restore the FPU registers */
+#endif
+
+ /* Returning with a pending context switch is different from the normal
+ * return because in this case, the register save structure does not lie
+ * on the stack but, rather, are within a TCB structure. We'll have to
+ * copy somevalues to the new stack.
+ */
+
+ add r1, r0, #SW_XCPT_SIZE /* R1=Address of HW save area in reg array */
+ ldmia r1, {r4-r11} /* Fetch eight registers in HW save area */
+ ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */
+ stmdb r1!, {r4-r11} /* Store eight registers in HW save area */
+#ifdef CONFIG_NUTTX_KERNEL
+ ldmia r0, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */
+#else
+ ldmia r0, {r2-r11} /* Recover R4-R11 + 2 temp values */
+#endif
+ b 2f /* Re-join common logic */
+
+ /* We are returning with no context switch. We simply need to "unwind"
+ * the same stack frame that we created
+ *
+ * Here:
+ * r1 = Address of the return stack (same as r0)
+ */
+1:
+#ifdef CONFIG_NUTTX_KERNEL
+ ldmia r1!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */
+#else
+ ldmia r1!, {r2-r11} /* Recover R4-R11 + 2 temp values */
+#endif
+#ifdef CONFIG_ARCH_FPU
+ /* Skip over the block of memory reserved for floating pointer register
+ * save. Then R1 is the address of the HW save area
+ */
+
+ add r1, #(4*SW_FPU_REGS)
+#endif
+
+ /* Set up to return from the exception
+ *
+ * Here:
+ * r1 = Address on the target thread's stack position at the start of
+ * the registers saved by hardware
+ * r3 = primask
+ * r4-r11 = restored register values
+ */
+2:
+#ifdef CONFIG_NUTTX_KERNEL
+ /* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1
+ * (handler mode) if the state is on the MSP. It can only be on the PSP if
+ * EXC_RETURN is 0xfffffffd (unprivileged thread)
+ */
+
+ adds r0, r14, #3 /* If R14=0xfffffffd, then r0 == 0 */
+ ite ne /* Next two instructions are condition */
+ msrne msp, r1 /* R1=The main stack pointer */
+ msreq psp, r1 /* R1=The process stack pointer */
+#else
+ msr msp, r1 /* Recover the return MSP value */
+
+ /* Preload r14 with the special return value first (so that the return
+ * actually occurs with interrupts still disabled).
+ */
+
+ ldr r14, =EXC_RETURN /* Load the special value */
+#endif
+
+ /* Restore the interrupt state */
+
+ msr primask, r3 /* Restore interrupts */
+
+ /* Always return with R14 containing the special value that will: (1)
+ * return to thread mode, and (2) continue to use the MSP
+ */
+
+ bx r14 /* And return */
+ .size handlers, .-handlers
+
+/************************************************************************************
+ * Name: up_interruptstack/g_intstackbase
+ *
+ * Description:
+ * Shouldn't happen
+ *
+ ************************************************************************************/
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+ .bss
+ .global g_intstackbase
+ .align 4
+up_interruptstack:
+ .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3)
+g_intstackbase:
+ .size up_interruptstack, .-up_interruptstack
+#endif
+#endif /* CONFIG_ARMV7M_CMNVECTOR */
+
+/************************************************************************************
+ * .rodata
+ ************************************************************************************/
+
+ .section .rodata, "a"
+
+/* Variables: _sbss is the start of the BSS region (see ld.script) _ebss is the end
+ * of the BSS regsion (see ld.script). The idle task stack starts at the end of BSS
+ * and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE thread is the thread that
+ * the system boots on and, eventually, becomes the idle, do nothing task that runs
+ * only when there is nothing else to run. The heap continues from there until the
+ * end of memory. See g_heapbase below.
+ */
+
+ .globl g_heapbase
+ .type g_heapbase, object
+g_heapbase:
+ .long _ebss+CONFIG_IDLETHREAD_STACKSIZE
+ .size g_heapbase, .-g_heapbase
+
+ .end
+
diff --git a/nuttx/arch/arm/src/stm32/stm32_waste.c b/nuttx/arch/arm/src/stm32/stm32_waste.c
new file mode 100644
index 000000000..a680b8b0f
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_waste.c
@@ -0,0 +1,57 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_waste.c
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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 "stm32_waste.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+uint32_t idle_wastecounter = 0;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void up_waste(void)
+{
+ idle_wastecounter++;
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_waste.h b/nuttx/arch/arm/src/stm32/stm32_waste.h
new file mode 100644
index 000000000..fa734f432
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_waste.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_waste.h
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * 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_STM32_STM32_WASTE_H
+#define __ARCH_ARM_SRC_STM32_STM32_WASTE_H
+
+/* Waste CPU Time */
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/** Waste CPU Time
+ *
+ * up_waste() is the logic that will be executed when portions of kernel
+ * or user-app is polling some register or similar, waiting for desired
+ * status. This time is wasted away. This function offers a measure of
+ * badly written piece of software or some undesired behavior.
+ *
+ * At the same time this function adds to some IDLE time which portion
+ * cannot be used for other purposes (yet).
+ **/
+
+EXTERN void up_waste(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_RRC_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_wdg.h b/nuttx/arch/arm/src/stm32/stm32_wdg.h
new file mode 100644
index 000000000..38af388f9
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_wdg.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_wdg.h
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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_STM32_STM32_WDG_H
+#define __ARCH_ARM_SRC_STM32_STM32_WDG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "chip/stm32_wdg.h"
+
+#ifdef CONFIG_WATCHDOG
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_iwdginitialize
+ *
+ * Description:
+ * Initialize the IWDG watchdog time. The watchdog timer is intialized and
+ * registers as 'devpath. The initial state of the watchdog time is
+ * disabled.
+ *
+ * Input Parameters:
+ * devpath - The full path to the watchdog. This should be of the form
+ * /dev/watchdog0
+ * lsifreq - The calibrated LSI clock frequency
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_IWDG
+EXTERN void stm32_iwdginitialize(FAR const char *devpath, uint32_t lsifreq);
+#endif
+
+/****************************************************************************
+ * Name: stm32_wwdginitialize
+ *
+ * Description:
+ * Initialize the WWDG watchdog time. The watchdog timer is intialized and
+ * registers as 'devpath. The initial state of the watchdog time is
+ * disabled.
+ *
+ * Input Parameters:
+ * devpath - The full path to the watchdog. This should be of the form
+ * /dev/watchdog0
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_WWDG
+EXTERN void stm32_wwdginitialize(FAR const char *devpath);
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_WATCHDOG */
+#endif /* __ARCH_ARM_SRC_STM32_STM32_WDG_H */
diff --git a/nuttx/arch/arm/src/stm32/stm32_wwdg.c b/nuttx/arch/arm/src/stm32/stm32_wwdg.c
new file mode 100644
index 000000000..4506fa4e0
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32_wwdg.c
@@ -0,0 +1,807 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_wwdg.c
+ *
+ * Copyright (C) 2012 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 <nuttx/arch.h>
+
+#include <stdint.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/watchdog.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "chip/stm32_dbgmcu.h"
+#include "stm32_wdg.h"
+
+#if defined(CONFIG_WATCHDOG) && defined(CONFIG_STM32_WWDG)
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+/* Clocking *****************************************************************/
+/* The minimum frequency of the WWDG clock is:
+ *
+ * Fmin = PCLK1 / 4096 / 8
+ *
+ * So the maximum delay (in milliseconds) is then:
+ *
+ * 1000 * (WWDG_CR_T_MAX+1) / Fmin
+ *
+ * For example, if PCLK1 = 42MHz, then the maximum delay is:
+ *
+ * Fmin = 1281.74
+ * 1000 * 64 / Fmin = 49.93 msec
+ */
+
+#define WWDG_FMIN (STM32_PCLK1_FREQUENCY / 4096 / 8)
+#define WWDG_MAXTIMEOUT (1000 * (WWDG_CR_T_MAX+1) / WWDG_FMIN)
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_STM32_WWDG_DEFTIMOUT
+# define CONFIG_STM32_WWDG_DEFTIMOUT WWDG_MAXTIMEOUT
+#endif
+
+/* Debug ********************************************************************/
+/* Non-standard debug that may be enabled just for testing the watchdog
+ * driver. NOTE: that only lldbg types are used so that the output is
+ * immediately available.
+ */
+
+#ifdef CONFIG_DEBUG_WATCHDOG
+# define wddbg lldbg
+# define wdvdbg llvdbg
+#else
+# define wddbg(x...)
+# define wdvdbg(x...)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+/* This structure provides the private representation of the "lower-half"
+ * driver state structure. This structure must be cast-compatible with the
+ * well-known watchdog_lowerhalf_s structure.
+ */
+
+struct stm32_lowerhalf_s
+{
+ FAR const struct watchdog_ops_s *ops; /* Lower half operations */
+ xcpt_t handler; /* Current EWI interrupt handler */
+ uint32_t timeout; /* The actual timeout value */
+ uint32_t fwwdg; /* WWDG clock frequency */
+ bool started; /* The timer has been started */
+ uint8_t reload; /* The 7-bit reload field reset value */
+ uint8_t window; /* The 7-bit window (W) field value */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+/* Register operations ******************************************************/
+
+#if defined(CONFIG_STM32_WWDG_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint16_t stm32_getreg(uint32_t addr);
+static void stm32_putreg(uint16_t val, uint32_t addr);
+#else
+# define stm32_getreg(addr) getreg32(addr)
+# define stm32_putreg(val,addr) putreg32(val,addr)
+#endif
+static void stm32_setwindow(FAR struct stm32_lowerhalf_s *priv,
+ uint8_t window);
+
+/* Interrupt hanlding *******************************************************/
+
+static int stm32_interrupt(int irq, FAR void *context);
+
+/* "Lower half" driver methods **********************************************/
+
+static int stm32_start(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower);
+static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status);
+static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout);
+static xcpt_t stm32_capture(FAR struct watchdog_lowerhalf_s *lower,
+ xcpt_t handler);
+static int stm32_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
+ unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+/* "Lower half" driver methods */
+
+static const struct watchdog_ops_s g_wdgops =
+{
+ .start = stm32_start,
+ .stop = stm32_stop,
+ .keepalive = stm32_keepalive,
+ .getstatus = stm32_getstatus,
+ .settimeout = stm32_settimeout,
+ .capture = stm32_capture,
+ .ioctl = stm32_ioctl,
+};
+
+/* "Lower half" driver state */
+
+static struct stm32_lowerhalf_s g_wdgdev;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_getreg
+ *
+ * Description:
+ * Get the contents of an STM32 register
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_WWDG_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint16_t stm32_getreg(uint32_t addr)
+{
+ static uint32_t prevaddr = 0;
+ static uint32_t count = 0;
+ static uint16_t preval = 0;
+
+ /* Read the value from the register */
+
+ uint16_t val = getreg16(addr);
+
+ /* Is this the same value that we read from the same registe last time? Are
+ * we polling the register? If so, suppress some of the output.
+ */
+
+ if (addr == prevaddr && val == preval)
+ {
+ if (count == 0xffffffff || ++count > 3)
+ {
+ if (count == 4)
+ {
+ lldbg("...\n");
+ }
+ return val;
+ }
+ }
+
+ /* No this is a new address or value */
+
+ else
+ {
+ /* Did we print "..." for the previous value? */
+
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
+
+ lldbg("[repeats %d more times]\n", count-3);
+ }
+
+ /* Save the new address, value, and count */
+
+ prevaddr = addr;
+ preval = val;
+ count = 1;
+ }
+
+ /* Show the register value read */
+
+ lldbg("%08x->%04x\n", addr, val);
+ return val;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_putreg
+ *
+ * Description:
+ * Set the contents of an STM32 register to a value
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_STM32_WWDG_REGDEBUG) && defined(CONFIG_DEBUG)
+static void stm32_putreg(uint16_t val, uint32_t addr)
+{
+ /* Show the register value being written */
+
+ lldbg("%08x<-%04x\n", addr, val);
+
+ /* Write the value */
+
+ putreg16(val, addr);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_setwindow
+ *
+ * Description:
+ * Set the CFR window value. The window value is compared to the down-
+ * counter when the counter is updated. The WWDG counter should be updated
+ * only when the counter is below this window value (and greater than 64)
+ * otherwise a reset will be generated
+ *
+ ****************************************************************************/
+
+static void stm32_setwindow(FAR struct stm32_lowerhalf_s *priv, uint8_t window)
+{
+ uint16_t regval;
+
+ /* Set W[6:0] bits according to selected window value */
+
+ regval = stm32_getreg(STM32_WWDG_CFR);
+ regval &= ~WWDG_CFR_W_MASK;
+ regval |= window << WWDG_CFR_W_SHIFT;
+ stm32_putreg(regval, STM32_WWDG_CFR);
+
+ /* Remember the window setting */
+
+ priv->window = window;
+}
+
+/****************************************************************************
+ * Name: stm32_interrupt
+ *
+ * Description:
+ * WWDG early warning interrupt
+ *
+ * Input Parameters:
+ * Usual interrupt handler arguments.
+ *
+ * Returned Values:
+ * Always returns OK.
+ *
+ ****************************************************************************/
+
+static int stm32_interrupt(int irq, FAR void *context)
+{
+ FAR struct stm32_lowerhalf_s *priv = &g_wdgdev;
+ uint16_t regval;
+
+ /* Check if the EWI interrupt is really pending */
+
+ regval = stm32_getreg(STM32_WWDG_SR);
+ if ((regval & WWDG_SR_EWIF) != 0)
+ {
+ /* Is there a registered handler? */
+
+ if (priv->handler)
+ {
+ /* Yes... NOTE: This interrupt service routine (ISR) must reload
+ * the WWDG counter to prevent the reset. Otherwise, we will reset
+ * upon return.
+ */
+
+ priv->handler(irq, context);
+ }
+
+ /* The EWI interrupt is cleared by writing '0' to the EWIF bit in the
+ * WWDG_SR register.
+ */
+
+ regval &= ~WWDG_SR_EWIF;
+ stm32_putreg(regval, STM32_WWDG_SR);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_start
+ *
+ * Description:
+ * Start the watchdog timer, resetting the time to the current timeout,
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_start(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+
+ wdvdbg("Entry\n");
+ DEBUGASSERT(priv);
+
+ /* The watchdog is always disabled after a reset. It is enabled by setting
+ * the WDGA bit in the WWDG_CR register, then it cannot be disabled again
+ * except by a reset.
+ */
+
+ stm32_putreg(WWDG_CR_WDGA | WWDG_CR_T_RESET | priv->reload, STM32_WWDG_CR);
+ priv->started = true;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_stop
+ *
+ * Description:
+ * Stop the watchdog timer
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower)
+{
+ /* The watchdog is always disabled after a reset. It is enabled by setting
+ * the WDGA bit in the WWDG_CR register, then it cannot be disabled again
+ * except by a reset.
+ */
+
+ wdvdbg("Entry\n");
+ return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: stm32_keepalive
+ *
+ * Description:
+ * Reset the watchdog timer to the current timeout value, prevent any
+ * imminent watchdog timeouts. This is sometimes referred as "pinging"
+ * the atchdog timer or "petting the dog".
+ *
+ * The application program must write in the WWDG_CR register at regular
+ * intervals during normal operation to prevent an MCU reset. This operation
+ * must occur only when the counter value is lower than the window register
+ * value. The value to be stored in the WWDG_CR register must be between
+ * 0xff and 0xC0:
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+
+ wdvdbg("Entry\n");
+ DEBUGASSERT(priv);
+
+ /* Write to T[6:0] bits to configure the counter value, no need to do
+ * a read-modify-write; writing a 0 to WDGA bit does nothing.
+ */
+
+ stm32_putreg((WWDG_CR_T_RESET | priv->reload), STM32_WWDG_CR);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_getstatus
+ *
+ * Description:
+ * Get the current watchdog timer status
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ * stawtus - The location to return the watchdog status information.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ uint32_t elapsed;
+ uint16_t reload;
+
+ wdvdbg("Entry\n");
+ DEBUGASSERT(priv);
+
+ /* Return the status bit */
+
+ status->flags = WDFLAGS_RESET;
+ if (priv->started)
+ {
+ status->flags |= WDFLAGS_ACTIVE;
+ }
+
+ if (priv->handler)
+ {
+ status->flags |= WDFLAGS_CAPTURE;
+ }
+
+ /* Return the actual timeout is milliseconds */
+
+ status->timeout = priv->timeout;
+
+ /* Get the time remaining until the watchdog expires (in milliseconds) */
+
+ reload = (stm32_getreg(STM32_WWDG_CR) >> WWDG_CR_T_SHIFT) & 0x7f;
+ elapsed = priv->reload - reload;
+ status->timeleft = (priv->timeout * elapsed) / (priv->reload + 1);
+
+ wdvdbg("Status :\n");
+ wdvdbg(" flags : %08x\n", status->flags);
+ wdvdbg(" timeout : %d\n", status->timeout);
+ wdvdbg(" timeleft : %d\n", status->flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_settimeout
+ *
+ * Description:
+ * Set a new timeout value (and reset the watchdog timer)
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ * timeout - The new timeout value in millisecnds.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ uint32_t fwwdg;
+ uint32_t reload;
+ uint16_t regval;
+ int wdgtb;
+
+ DEBUGASSERT(priv);
+ wdvdbg("Entry: timeout=%d\n", timeout);
+
+ /* Can this timeout be represented? */
+
+ if (timeout < 1 || timeout > WWDG_MAXTIMEOUT)
+ {
+ wddbg("Cannot represent timeout=%d > %d\n",
+ timeout, WWDG_MAXTIMEOUT);
+ return -ERANGE;
+ }
+
+ /* Determine prescaler value.
+ *
+ * Fwwdg = PCLK1/4096/prescaler.
+ *
+ * Where
+ * Fwwwdg is the frequency of the WWDG clock
+ * wdgtb is one of {1, 2, 4, or 8}
+ */
+
+ /* Select the smallest prescaler that will result in a reload field value that is
+ * less than the maximum.
+ */
+
+ for (wdgtb = 0; ; wdgtb++)
+ {
+ /* WDGTB = 0 -> Divider = 1 = 1 << 0
+ * WDGTB = 1 -> Divider = 2 = 1 << 1
+ * WDGTB = 2 -> Divider = 4 = 1 << 2
+ * WDGTB = 3 -> Divider = 8 = 1 << 3
+ */
+
+ /* Get the WWDG counter frequency in Hz. */
+
+ fwwdg = (STM32_PCLK1_FREQUENCY/4096) >> wdgtb;
+
+ /* The formula to calculate the timeout value is given by:
+ *
+ * timeout = 1000 * (reload + 1) / Fwwdg, OR
+ * reload = timeout * Fwwdg / 1000 - 1
+ *
+ * Where
+ * timeout is the desired timout in milliseconds
+ * reload is the contents of T{5:0]
+ * Fwwdg is the frequency of the WWDG clock
+ */
+
+ reload = timeout * fwwdg / 1000 - 1;
+
+ /* If this reload valid is less than the maximum or we are not ready
+ * at the prescaler value, then break out of the loop to use these
+ * settings.
+ */
+
+#if 0
+ wdvdbg("wdgtb=%d fwwdg=%d reload=%d timout=%d\n",
+ wdgtb, fwwdg, reload, 1000 * (reload + 1) / fwwdg);
+#endif
+ if (reload <= WWDG_CR_T_MAX || wdgtb == 3)
+ {
+ /* Note that we explicity break out of the loop rather than using
+ * the 'for' loop termination logic because we do not want the
+ * value of wdgtb to be incremented.
+ */
+
+ break;
+ }
+ }
+
+ /* Make sure that the final reload value is within range */
+
+ if (reload > WWDG_CR_T_MAX)
+ {
+ reload = WWDG_CR_T_MAX;
+ }
+
+ /* Calculate and save the actual timeout value in milliseconds:
+ *
+ * timeout = 1000 * (reload + 1) / Fwwdg
+ */
+
+ priv->timeout = 1000 * (reload + 1) / fwwdg;
+
+ /* Remember the selected values */
+
+ priv->fwwdg = fwwdg;
+ priv->reload = reload;
+
+ wdvdbg("wdgtb=%d fwwdg=%d reload=%d timout=%d\n",
+ wdgtb, fwwdg, reload, priv->timeout);
+
+ /* Set WDGTB[1:0] bits according to calculated value */
+
+ regval = stm32_getreg(STM32_WWDG_CFR);
+ regval &= ~WWDG_CFR_WDGTB_MASK;
+ regval |= (uint16_t)wdgtb << WWDG_CFR_WDGTB_SHIFT;
+ stm32_putreg(regval, STM32_WWDG_CFR);
+
+ /* Reset the 7-bit window value to the maximum value.. essentially disabling
+ * the lower limit of the watchdog reset time.
+ */
+
+ stm32_setwindow(priv, 0x7f);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_capture
+ *
+ * Description:
+ * Don't reset on watchdog timer timeout; instead, call this user provider
+ * timeout handler. NOTE: Providing handler==NULL will restore the reset
+ * behavior.
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ * newhandler - The new watchdog expiration function pointer. If this
+ * function pointer is NULL, then the the reset-on-expiration
+ * behavior is restored,
+ *
+ * Returned Values:
+ * The previous watchdog expiration function pointer or NULL is there was
+ * no previous function pointer, i.e., if the previous behavior was
+ * reset-on-expiration (NULL is also returned if an error occurs).
+ *
+ ****************************************************************************/
+
+static xcpt_t stm32_capture(FAR struct watchdog_lowerhalf_s *lower,
+ xcpt_t handler)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ irqstate_t flags;
+ xcpt_t oldhandler;
+ uint16_t regval;
+
+ DEBUGASSERT(priv);
+ wdvdbg("Entry: handler=%p\n", handler);
+
+ /* Get the old handler return value */
+
+ flags = irqsave();
+ oldhandler = priv->handler;
+
+ /* Save the new handler */
+
+ priv->handler = handler;
+
+ /* Are we attaching or detaching the handler? */
+
+ regval = stm32_getreg(STM32_WWDG_CFR);
+ if (handler)
+ {
+ /* Attaching... Enable the EWI interrupt */
+
+ regval |= WWDG_CFR_EWI;
+ stm32_putreg(regval, STM32_WWDG_CFR);
+
+ up_enable_irq(STM32_IRQ_WWDG);
+ }
+ else
+ {
+ /* Detaching... Disable the EWI interrupt */
+
+ regval &= ~WWDG_CFR_EWI;
+ stm32_putreg(regval, STM32_WWDG_CFR);
+
+ up_disable_irq(STM32_IRQ_WWDG);
+ }
+
+ irqrestore(flags);
+ return oldhandler;
+}
+
+/****************************************************************************
+ * Name: stm32_ioctl
+ *
+ * Description:
+ * Any ioctl commands that are not recognized by the "upper-half" driver
+ * are forwarded to the lower half driver through this method.
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the "lower-half"
+ * driver state structure.
+ * cmd - The ioctol command value
+ * arg - The optional argument that accompanies the 'cmd'. The
+ * interpretation of this argument depends on the particular
+ * command.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
+ unsigned long arg)
+{
+ FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
+ int ret = -ENOTTY;
+
+ DEBUGASSERT(priv);
+ wdvdbg("Entry: cmd=%d arg=%ld\n", cmd, arg);
+
+ /* WDIOC_MINTIME: Set the minimum ping time. If two keepalive ioctls
+ * are received within this time, a reset event will be generated.
+ * Argument: A 32-bit time value in milliseconds.
+ */
+
+ if (cmd == WDIOC_MINTIME)
+ {
+ uint32_t mintime = (uint32_t)arg;
+
+ /* The minimum time should be strictly less than the total delay
+ * which, in turn, will be less than or equal to WWDG_CR_T_MAX
+ */
+
+ ret = -EINVAL;
+ if (mintime < priv->timeout)
+ {
+ uint32_t window = (priv->timeout - mintime) * priv->fwwdg / 1000 - 1;
+ DEBUGASSERT(window < priv->reload);
+ stm32_setwindow(priv, window | WWDG_CR_T_RESET);
+ ret = OK;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_wwdginitialize
+ *
+ * Description:
+ * Initialize the WWDG watchdog time. The watchdog timer is intialized and
+ * registers as 'devpath. The initial state of the watchdog time is
+ * disabled.
+ *
+ * Input Parameters:
+ * devpath - The full path to the watchdog. This should be of the form
+ * /dev/watchdog0
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+void stm32_wwdginitialize(FAR const char *devpath)
+{
+ FAR struct stm32_lowerhalf_s *priv = &g_wdgdev;
+
+ wdvdbg("Entry: devpath=%s\n", devpath);
+
+ /* NOTE we assume that clocking to the IWDG has already been provided by
+ * the RCC initialization logic.
+ */
+
+ /* Initialize the driver state structure. Here we assume: (1) the state
+ * structure lies in .bss and was zeroed at reset time. (2) This function
+ * is only called once so it is never necessary to re-zero the structure.
+ */
+
+ priv->ops = &g_wdgops;
+
+ /* Attach our EWI interrupt handler (But don't enable it yet) */
+
+ (void)irq_attach(STM32_IRQ_WWDG, stm32_interrupt);
+
+ /* Select an arbitrary initial timeout value. But don't start the watchdog
+ * yet. NOTE: If the "Hardware watchdog" feature is enabled through the
+ * device option bits, the watchdog is automatically enabled at power-on.
+ */
+
+ stm32_settimeout((FAR struct watchdog_lowerhalf_s *)priv,
+ CONFIG_STM32_WWDG_DEFTIMOUT);
+
+ /* Register the watchdog driver as /dev/watchdog0 */
+
+ (void)watchdog_register(devpath, (FAR struct watchdog_lowerhalf_s *)priv);
+
+ /* When the microcontroller enters debug mode (Cortex™-M4F core halted),
+ * the WWDG counter either continues to work normally or stops, depending
+ * on DBG_WWDG_STOP configuration bit in DBG module.
+ */
+
+#if defined(CONFIG_STM32_JTAG_FULL_ENABLE) || \
+ defined(CONFIG_STM32_JTAG_NOJNTRST_ENABLE) || \
+ defined(CONFIG_STM32_JTAG_SW_ENABLE)
+ {
+ uint32_t cr = getreg32(STM32_DBGMCU_CR);
+ cr |= DBGMCU_CR_WWDGSTOP;
+ putreg32(cr, STM32_DBGMCU_CR);
+ }
+#endif
+}
+
+#endif /* CONFIG_WATCHDOG && CONFIG_STM32_WWDG */
diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c
new file mode 100644
index 000000000..89b279bea
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c
@@ -0,0 +1,615 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32f10xxx_dma.c
+ *
+ * Copyright (C) 2009, 2011-2012 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 <stdbool.h>
+#include <semaphore.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/irq.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+#include "os_internal.h"
+#include "chip.h"
+#include "stm32_dma.h"
+#include "stm32_internal.h"
+
+/* Only for the STM32F10xx family for now */
+
+#ifdef CONFIG_STM32_STM32F10XX
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DMA1_NCHANNELS 7
+#if STM32_NDMA > 1
+# define DMA2_NCHANNELS 5
+# define DMA_NCHANNELS (DMA1_NCHANNELS+DMA2_NCHANNELS)
+#else
+# define DMA_NCHANNELS DMA1_NCHANNELS
+#endif
+
+#ifndef CONFIG_DMA_PRI
+# define CONFIG_DMA_PRI NVIC_SYSH_PRIORITY_DEFAULT
+#endif
+
+/* Convert the DMA channel base address to the DMA register block address */
+
+#define DMA_BASE(ch) (ch & 0xfffffc00)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure descibes one DMA channel */
+
+struct stm32_dma_s
+{
+ uint8_t chan; /* DMA channel number (0-6) */
+ uint8_t irq; /* DMA channel IRQ number */
+ sem_t sem; /* Used to wait for DMA channel to become available */
+ uint32_t base; /* DMA register channel base address */
+ dma_callback_t callback; /* Callback invoked when the DMA completes */
+ void *arg; /* Argument passed to callback function */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This array describes the state of each DMA */
+
+static struct stm32_dma_s g_dma[DMA_NCHANNELS] =
+{
+ {
+ .chan = 0,
+ .irq = STM32_IRQ_DMA1CH1,
+ .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(0),
+ },
+ {
+ .chan = 1,
+ .irq = STM32_IRQ_DMA1CH2,
+ .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(1),
+ },
+ {
+ .chan = 2,
+ .irq = STM32_IRQ_DMA1CH3,
+ .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(2),
+ },
+ {
+ .chan = 3,
+ .irq = STM32_IRQ_DMA1CH4,
+ .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(3),
+ },
+ {
+ .chan = 4,
+ .irq = STM32_IRQ_DMA1CH5,
+ .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(4),
+ },
+ {
+ .chan = 5,
+ .irq = STM32_IRQ_DMA1CH6,
+ .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(5),
+ },
+ {
+ .chan = 6,
+ .irq = STM32_IRQ_DMA1CH7,
+ .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(6),
+ },
+#if STM32_NDMA > 1
+ {
+ .chan = 0,
+ .irq = STM32_IRQ_DMA2CH1,
+ .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(0),
+ },
+ {
+ .chan = 1,
+ .irq = STM32_IRQ_DMA2CH2,
+ .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(1),
+ },
+ {
+ .chan = 2,
+ .irq = STM32_IRQ_DMA2CH3,
+ .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(2),
+ },
+ {
+ .chan = 3,
+#ifdef CONFIG_STM32_CONNECTIVITYLINE
+ .irq = STM32_IRQ_DMA2CH4,
+#else
+ .irq = STM32_IRQ_DMA2CH45,
+#endif
+ .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(3),
+ },
+ {
+ .chan = 4,
+#ifdef CONFIG_STM32_CONNECTIVITYLINE
+ .irq = STM32_IRQ_DMA2CH5,
+#else
+ .irq = STM32_IRQ_DMA2CH45,
+#endif
+ .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(4),
+ },
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * DMA register access functions
+ ****************************************************************************/
+
+/* Get non-channel register from DMA1 or DMA2 */
+
+static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmach, uint32_t offset)
+{
+ return getreg32(DMA_BASE(dmach->base) + offset);
+}
+
+/* Write to non-channel register in DMA1 or DMA2 */
+
+static inline void dmabase_putreg(struct stm32_dma_s *dmach, uint32_t offset, uint32_t value)
+{
+ putreg32(value, DMA_BASE(dmach->base) + offset);
+}
+
+/* Get channel register from DMA1 or DMA2 */
+
+static inline uint32_t dmachan_getreg(struct stm32_dma_s *dmach, uint32_t offset)
+{
+ return getreg32(dmach->base + offset);
+}
+
+/* Write to channel register in DMA1 or DMA2 */
+
+static inline void dmachan_putreg(struct stm32_dma_s *dmach, uint32_t offset, uint32_t value)
+{
+ putreg32(value, dmach->base + offset);
+}
+
+/************************************************************************************
+ * Name: stm32_dmatake() and stm32_dmagive()
+ *
+ * Description:
+ * Used to get exclusive access to a DMA channel.
+ *
+ ************************************************************************************/
+
+static void stm32_dmatake(FAR struct stm32_dma_s *dmach)
+{
+ /* Take the semaphore (perhaps waiting) */
+
+ while (sem_wait(&dmach->sem) != 0)
+ {
+ /* The only case that an error should occur here is if the wait was awakened
+ * by a signal.
+ */
+
+ ASSERT(errno == EINTR);
+ }
+}
+
+static inline void stm32_dmagive(FAR struct stm32_dma_s *dmach)
+{
+ (void)sem_post(&dmach->sem);
+}
+
+/************************************************************************************
+ * Name: stm32_dmachandisable
+ *
+ * Description:
+ * Disable the DMA channel
+ *
+ ************************************************************************************/
+
+static void stm32_dmachandisable(struct stm32_dma_s *dmach)
+{
+ uint32_t regval;
+
+ /* Disable all interrupts at the DMA controller */
+
+ regval = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET);
+ regval &= ~DMA_CCR_ALLINTS;
+
+ /* Disable the DMA channel */
+
+ regval &= ~DMA_CCR_EN;
+ dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, regval);
+
+ /* Clear pending channel interrupts */
+
+ dmabase_putreg(dmach, STM32_DMA_IFCR_OFFSET, DMA_ISR_CHAN_MASK(dmach->chan));
+}
+
+/************************************************************************************
+ * Name: stm32_dmainterrupt
+ *
+ * Description:
+ * DMA interrupt handler
+ *
+ ************************************************************************************/
+
+static int stm32_dmainterrupt(int irq, void *context)
+{
+ struct stm32_dma_s *dmach;
+ uint32_t isr;
+ int chndx = 0;
+
+ /* Get the channel structure from the interrupt number */
+
+ if (irq >= STM32_IRQ_DMA1CH1 && irq <= STM32_IRQ_DMA1CH7)
+ {
+ chndx = irq - STM32_IRQ_DMA1CH1;
+ }
+ else
+#if STM32_NDMA > 1
+#ifdef CONFIG_STM32_CONNECTIVITYLINE
+ if (irq >= STM32_IRQ_DMA2CH1 && irq <= STM32_IRQ_DMA2CH5)
+#else
+ if (irq >= STM32_IRQ_DMA2CH1 && irq <= STM32_IRQ_DMA2CH45)
+#endif
+ {
+ chndx = irq - STM32_IRQ_DMA2CH1 + DMA1_NCHANNELS;
+ }
+ else
+#endif
+ {
+ PANIC(OSERR_INTERNAL);
+ }
+ dmach = &g_dma[chndx];
+
+ /* Get the interrupt status (for this channel only) -- not currently used */
+
+ isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET) & DMA_ISR_CHAN_MASK(dmach->chan);
+
+ /* Disable the DMA channel */
+
+ stm32_dmachandisable(dmach);
+
+ /* Invoke the callback */
+
+ if (dmach->callback)
+ {
+ dmach->callback(dmach, isr >> DMA_ISR_CHAN_SHIFT(dmach->chan), dmach->arg);
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_dmainitialize
+ *
+ * Description:
+ * Initialize the DMA subsystem
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void weak_function up_dmainitialize(void)
+{
+ struct stm32_dma_s *dmach;
+ int chndx;
+
+ /* Initialize each DMA channel */
+
+ for (chndx = 0; chndx < DMA_NCHANNELS; chndx++)
+ {
+ dmach = &g_dma[chndx];
+ sem_init(&dmach->sem, 0, 1);
+
+ /* Attach DMA interrupt vectors */
+
+ (void)irq_attach(dmach->irq, stm32_dmainterrupt);
+
+ /* Disable the DMA channel */
+
+ stm32_dmachandisable(dmach);
+
+ /* Enable the IRQ at the NVIC (still disabled at the DMA controller) */
+
+ up_enable_irq(dmach->irq);
+
+ /* Set the interrrupt priority */
+
+ up_prioritize_irq(dmach->irq, CONFIG_DMA_PRI);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_dmachannel
+ *
+ * Description:
+ * Allocate a DMA channel. This function gives the caller mutually
+ * exclusive access to the DMA channel specified by the 'chndx' argument.
+ * DMA channels are shared on the STM32: Devices sharing the same DMA
+ * channel cannot do DMA concurrently! See the DMACHAN_* definitions in
+ * stm32_dma.h.
+ *
+ * If the DMA channel is not available, then stm32_dmachannel() will wait
+ * until the holder of the channel relinquishes the channel by calling
+ * stm32_dmafree(). WARNING: If you have two devices sharing a DMA
+ * channel and the code never releases the channel, the stm32_dmachannel
+ * call for the other will hang forever in this function! Don't let your
+ * design do that!
+ *
+ * Hmm.. I suppose this interface could be extended to make a non-blocking
+ * version. Feel free to do that if that is what you need.
+ *
+ * Input parameter:
+ * chndx - Identifies the stream/channel resource. For the STM32 F1, this
+ * is simply the channel number as provided by the DMACHAN_* definitions
+ * in chip/stm32f10xxx_dma.h.
+ *
+ * Returned Value:
+ * Provided that 'chndx' is valid, this function ALWAYS returns a non-NULL,
+ * void* DMA channel handle. (If 'chndx' is invalid, the function will
+ * assert if debug is enabled or do something ignorant otherwise).
+ *
+ * Assumptions:
+ * - The caller does not hold he DMA channel.
+ * - The caller can wait for the DMA channel to be freed if it is no
+ * available.
+ *
+ ****************************************************************************/
+
+DMA_HANDLE stm32_dmachannel(unsigned int chndx)
+{
+ struct stm32_dma_s *dmach = &g_dma[chndx];
+
+ DEBUGASSERT(chndx < DMA_NCHANNELS);
+
+ /* Get exclusive access to the DMA channel -- OR wait until the channel
+ * is available if it is currently being used by another driver
+ */
+
+ stm32_dmatake(dmach);
+
+ /* The caller now has exclusive use of the DMA channel */
+
+ return (DMA_HANDLE)dmach;
+}
+
+/****************************************************************************
+ * Name: stm32_dmafree
+ *
+ * Description:
+ * Release a DMA channel. If another thread is waiting for this DMA channel
+ * in a call to stm32_dmachannel, then this function will re-assign the
+ * DMA channel to that thread and wake it up. NOTE: The 'handle' used
+ * in this argument must NEVER be used again until stm32_dmachannel() is
+ * called again to re-gain access to the channel.
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * - The caller holds the DMA channel.
+ * - There is no DMA in progress
+ *
+ ****************************************************************************/
+
+void stm32_dmafree(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle;
+
+ DEBUGASSERT(handle != NULL);
+
+ /* Release the channel */
+
+ stm32_dmagive(dmach);
+}
+
+/****************************************************************************
+ * Name: stm32_dmasetup
+ *
+ * Description:
+ * Configure DMA before using
+ *
+ ****************************************************************************/
+
+void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t ntransfers, uint32_t ccr)
+{
+ struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle;
+ uint32_t regval;
+
+ /* Set the peripheral register address in the DMA_CPARx register. The data
+ * will be moved from/to this address to/from the memory after the
+ * peripheral event.
+ */
+
+ dmachan_putreg(dmach, STM32_DMACHAN_CPAR_OFFSET, paddr);
+
+ /* Set the memory address in the DMA_CMARx register. The data will be
+ * written to or read from this memory after the peripheral event.
+ */
+
+ dmachan_putreg(dmach, STM32_DMACHAN_CMAR_OFFSET, maddr);
+
+ /* Configure the total number of data to be transferred in the DMA_CNDTRx
+ * register. After each peripheral event, this value will be decremented.
+ */
+
+ dmachan_putreg(dmach, STM32_DMACHAN_CNDTR_OFFSET, ntransfers);
+
+ /* Configure the channel priority using the PL[1:0] bits in the DMA_CCRx
+ * register. Configure data transfer direction, circular mode, peripheral & memory
+ * incremented mode, peripheral & memory data size, and interrupt after
+ * half and/or full transfer in the DMA_CCRx register.
+ */
+
+ regval = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET);
+ regval &= ~(DMA_CCR_MEM2MEM|DMA_CCR_PL_MASK|DMA_CCR_MSIZE_MASK|DMA_CCR_PSIZE_MASK|
+ DMA_CCR_MINC|DMA_CCR_PINC|DMA_CCR_CIRC|DMA_CCR_DIR);
+ ccr &= (DMA_CCR_MEM2MEM|DMA_CCR_PL_MASK|DMA_CCR_MSIZE_MASK|DMA_CCR_PSIZE_MASK|
+ DMA_CCR_MINC|DMA_CCR_PINC|DMA_CCR_CIRC|DMA_CCR_DIR);
+ regval |= ccr;
+ dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: stm32_dmastart
+ *
+ * Description:
+ * Start the DMA transfer
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ * - No DMA in progress
+ *
+ ****************************************************************************/
+
+void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool half)
+{
+ struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle;
+ uint32_t ccr;
+
+ DEBUGASSERT(handle != NULL);
+
+ /* Save the callback info. This will be invoked whent the DMA commpletes */
+
+ dmach->callback = callback;
+ dmach->arg = arg;
+
+ /* Activate the channel by setting the ENABLE bit in the DMA_CCRx register.
+ * As soon as the channel is enabled, it can serve any DMA request from the
+ * peripheral connected on the channel.
+ */
+
+ ccr = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET);
+ ccr |= DMA_CCR_EN;
+
+ /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
+ * set and an interrupt is generated if the Half-Transfer Interrupt Enable
+ * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
+ * (TCIF) is set and an interrupt is generated if the Transfer Complete
+ * Interrupt Enable bit (TCIE) is set.
+ */
+
+ ccr |= (half ? (DMA_CCR_HTIE|DMA_CCR_TEIE) : (DMA_CCR_TCIE|DMA_CCR_TEIE));
+ dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, ccr);
+}
+
+/****************************************************************************
+ * Name: stm32_dmastop
+ *
+ * Description:
+ * Cancel the DMA. After stm32_dmastop() is called, the DMA channel is
+ * reset and stm32_dmasetup() must be called before stm32_dmastart() can be
+ * called again
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+void stm32_dmastop(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle;
+ stm32_dmachandisable(dmach);
+}
+
+/****************************************************************************
+ * Name: stm32_dmasample
+ *
+ * Description:
+ * Sample DMA register contents
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_DMA
+void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs)
+{
+ struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle;
+ irqstate_t flags;
+
+ flags = irqsave();
+ regs->isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET);
+ regs->ccr = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET);
+ regs->cndtr = dmachan_getreg(dmach, STM32_DMACHAN_CNDTR_OFFSET);
+ regs->cpar = dmachan_getreg(dmach, STM32_DMACHAN_CPAR_OFFSET);
+ regs->cmar = dmachan_getreg(dmach, STM32_DMACHAN_CMAR_OFFSET);
+ irqrestore(flags);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_dmadump
+ *
+ * Description:
+ * Dump previously sampled DMA register contents
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_DMA
+void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs,
+ const char *msg)
+{
+ struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle;
+ uint32_t dmabase = DMA_BASE(dmach->base);
+
+ dmadbg("DMA Registers: %s\n", msg);
+ dmadbg(" ISRC[%08x]: %08x\n", dmabase + STM32_DMA_ISR_OFFSET, regs->isr);
+ dmadbg(" CCR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CCR_OFFSET, regs->ccr);
+ dmadbg(" CNDTR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CNDTR_OFFSET, regs->cndtr);
+ dmadbg(" CPAR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CPAR_OFFSET, regs->cpar);
+ dmadbg(" CMAR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CMAR_OFFSET, regs->cmar);
+}
+#endif
+
+#endif /* CONFIG_STM32_STM32F10XX */
diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c
new file mode 100644
index 000000000..516b026fb
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_rcc.c
@@ -0,0 +1,556 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32f10xxx_rcc.c
+ *
+ * Copyright (C) 2009, 2011-2012 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
+ ****************************************************************************/
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* Allow up to 100 milliseconds for the high speed clock to become ready.
+ * that is a very long delay, but if the clock does not become ready we are
+ * hosed anyway. Normally this is very fast, but I have seen at least one
+ * board that required this long, long timeout for the HSE to be ready.
+ */
+
+#define HSERDY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rcc_reset
+ *
+ * Description:
+ * Put all RCC registers in reset state
+ *
+ ****************************************************************************/
+
+static inline void rcc_reset(void)
+{
+ uint32_t regval;
+
+ putreg32(0, STM32_RCC_APB2RSTR); /* Disable APB2 Peripheral Reset */
+ putreg32(0, STM32_RCC_APB1RSTR); /* Disable APB1 Peripheral Reset */
+ putreg32(RCC_AHBENR_FLITFEN|RCC_AHBENR_SRAMEN, STM32_RCC_AHBENR); /* FLITF and SRAM Clock ON */
+ putreg32(0, STM32_RCC_APB2ENR); /* Disable APB2 Peripheral Clock */
+ putreg32(0, STM32_RCC_APB1ENR); /* Disable APB1 Peripheral Clock */
+
+ regval = getreg32(STM32_RCC_CR); /* Set the HSION bit */
+ regval |= RCC_CR_HSION;
+ putreg32(regval, STM32_RCC_CR);
+
+ regval = getreg32(STM32_RCC_CFGR); /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
+ regval &= ~(RCC_CFGR_SW_MASK|RCC_CFGR_HPRE_MASK|RCC_CFGR_PPRE1_MASK|RCC_CFGR_PPRE2_MASK|RCC_CFGR_ADCPRE_MASK|RCC_CFGR_MCO_MASK);
+ putreg32(regval, STM32_RCC_CFGR);
+
+ regval = getreg32(STM32_RCC_CR); /* Reset HSEON, CSSON and PLLON bits */
+ regval &= ~(RCC_CR_HSEON|RCC_CR_CSSON|RCC_CR_PLLON);
+ putreg32(regval, STM32_RCC_CR);
+
+ regval = getreg32(STM32_RCC_CR); /* Reset HSEBYP bit */
+ regval &= ~RCC_CR_HSEBYP;
+ putreg32(regval, STM32_RCC_CR);
+
+ regval = getreg32(STM32_RCC_CFGR); /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE bits */
+ regval &= ~(RCC_CFGR_PLLSRC|RCC_CFGR_PLLXTPRE|RCC_CFGR_PLLMUL_MASK|RCC_CFGR_USBPRE);
+ putreg32(regval, STM32_RCC_CFGR);
+
+ putreg32(0, STM32_RCC_CIR); /* Disable all interrupts */
+}
+
+/****************************************************************************
+ * Name: rcc_enableahb
+ *
+ * Description:
+ * Enable selected AHB peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableahb(void)
+{
+ uint32_t regval;
+
+ /* Always enable FLITF clock and SRAM clock */
+
+ regval = RCC_AHBENR_FLITFEN|RCC_AHBENR_SRAMEN;
+
+#ifdef CONFIG_STM32_DMA1
+ /* DMA 1 clock enable */
+
+ regval |= RCC_AHBENR_DMA1EN;
+#endif
+
+#ifdef CONFIG_STM32_DMA2
+ /* DMA 2 clock enable */
+
+ regval |= RCC_AHBENR_DMA2EN;
+#endif
+
+#ifdef CONFIG_STM32_CRC
+ /* CRC clock enable */
+
+ regval |= RCC_AHBENR_CRCEN;
+#endif
+
+#ifdef CONFIG_STM32_FSMC
+ /* FSMC clock enable */
+
+ regval |= RCC_AHBENR_FSMCEN;
+#endif
+
+#ifdef CONFIG_STM32_SDIO
+ /* SDIO clock enable */
+
+ regval |= RCC_AHBENR_SDIOEN;
+#endif
+
+ putreg32(regval, STM32_RCC_AHBENR); /* Enable peripherals */
+}
+
+/****************************************************************************
+ * Name: rcc_enableapb1
+ *
+ * Description:
+ * Enable selected APB1 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableapb1(void)
+{
+ uint32_t regval;
+
+#ifdef CONFIG_STM32_USB
+ /* USB clock divider. This bit must be valid before enabling the USB
+ * clock in the RCC_APB1ENR register. This bit can’t be reset if the USB
+ * clock is enabled.
+ */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_USBPRE;
+ regval |= STM32_CFGR_USBPRE;
+ putreg32(regval, STM32_RCC_CFGR);
+#endif
+
+ /* Set the appropriate bits in the APB1ENR register to enabled the
+ * selected APB1 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_APB1ENR);
+#ifdef CONFIG_STM32_TIM2
+ /* Timer 2 clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB1ENR_TIM2EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_TIM3
+ /* Timer 3 clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB1ENR_TIM3EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_TIM4
+ /* Timer 4 clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB1ENR_TIM4EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_TIM5
+ /* Timer 5 clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB1ENR_TIM5EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_TIM6
+ /* Timer 6 clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB1ENR_TIM6EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_TIM7
+ /* Timer 7 clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB1ENR_TIM7EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_WWDG
+ /* Window Watchdog clock enable */
+
+ regval |= RCC_APB1ENR_WWDGEN;
+#endif
+
+#ifdef CONFIG_STM32_SPI2
+ /* SPI 2 clock enable */
+
+ regval |= RCC_APB1ENR_SPI2EN;
+#endif
+
+#ifdef CONFIG_STM32_SPI3
+ /* SPI 3 clock enable */
+
+ regval |= RCC_APB1ENR_SPI3EN;
+#endif
+
+#ifdef CONFIG_STM32_USART2
+ /* USART 2 clock enable */
+
+ regval |= RCC_APB1ENR_USART2EN;
+#endif
+
+#ifdef CONFIG_STM32_USART3
+ /* USART 3 clock enable */
+
+ regval |= RCC_APB1ENR_USART3EN;
+#endif
+
+#ifdef CONFIG_STM32_UART4
+ /* UART 4 clock enable */
+
+ regval |= RCC_APB1ENR_UART4EN;
+#endif
+
+#ifdef CONFIG_STM32_UART5
+ /* UART 5 clock enable */
+
+ regval |= RCC_APB1ENR_UART5EN;
+#endif
+
+#ifdef CONFIG_STM32_I2C1
+ /* I2C 1 clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB1ENR_I2C1EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_I2C2
+ /* I2C 2 clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB1ENR_I2C2EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_USB
+ /* USB clock enable */
+
+ regval |= RCC_APB1ENR_USBEN;
+#endif
+
+#ifdef CONFIG_STM32_CAN1
+ /* CAN1 clock enable */
+
+ regval |= RCC_APB1ENR_CAN1EN;
+#endif
+
+#ifdef CONFIG_STM32_CAN2
+ /* CAN2 clock enable. NOTE: CAN2 needs CAN1 clock as well. */
+
+ regval |= (RCC_APB1ENR_CAN1EN | RCC_APB1ENR_CAN2EN);
+#endif
+
+#ifdef CONFIG_STM32_BKP
+ /* Backup interface clock enable */
+
+ regval |= RCC_APB1ENR_BKPEN;
+#endif
+
+#ifdef CONFIG_STM32_PWR
+ /* Power interface clock enable */
+
+ regval |= RCC_APB1ENR_PWREN;
+#endif
+
+#if defined(CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2)
+ /* DAC interface clock enable */
+
+ regval |= RCC_APB1ENR_DACEN;
+#endif
+ putreg32(regval, STM32_RCC_APB1ENR);
+}
+
+/****************************************************************************
+ * Name: rcc_enableapb2
+ *
+ * Description:
+ * Enable selected APB2 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableapb2(void)
+{
+ uint32_t regval;
+
+ /* Set the appropriate bits in the APB2ENR register to enabled the
+ * selected APB2 peripherals.
+ */
+
+ /* Enable GPIOA, GPIOB, ... and AFIO clocks */
+
+ regval = getreg32(STM32_RCC_APB2ENR);
+ regval |= (RCC_APB2ENR_AFIOEN
+#if STM32_NGPIO > 0
+ |RCC_APB2ENR_IOPAEN
+#endif
+#if STM32_NGPIO > 16
+ |RCC_APB2ENR_IOPBEN
+#endif
+#if STM32_NGPIO > 32
+ |RCC_APB2ENR_IOPCEN
+#endif
+#if STM32_NGPIO > 48
+ |RCC_APB2ENR_IOPDEN
+#endif
+#if STM32_NGPIO > 64
+ |RCC_APB2ENR_IOPEEN
+#endif
+#if STM32_NGPIO > 80
+ |RCC_APB2ENR_IOPFEN
+#endif
+#if STM32_NGPIO > 96
+ |RCC_APB2ENR_IOPGEN
+#endif
+ );
+
+#ifdef CONFIG_STM32_ADC1
+ /* ADC 1 interface clock enable */
+
+ regval |= RCC_APB2ENR_ADC1EN;
+#endif
+
+#ifdef CONFIG_STM32_ADC2
+ /* ADC 2 interface clock enable */
+
+ regval |= RCC_APB2ENR_ADC2EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM1
+ /* TIM1 Timer clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB2ENR_TIM1EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_SPI1
+ /* SPI 1 clock enable */
+
+ regval |= RCC_APB2ENR_SPI1EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM8
+ /* TIM8 Timer clock enable */
+#ifdef CONFIG_STM32_FORCEPOWER
+ regval |= RCC_APB2ENR_TIM8EN;
+#endif
+#endif
+
+#ifdef CONFIG_STM32_USART1
+ /* USART1 clock enable */
+
+ regval |= RCC_APB2ENR_USART1EN;
+#endif
+
+#ifdef CONFIG_STM32_ADC3
+ /*ADC3 interface clock enable */
+
+ regval |= RCC_APB2ENR_ADC3EN;
+#endif
+ putreg32(regval, STM32_RCC_APB2ENR);
+}
+
+/****************************************************************************
+ * Name: stm32_stdclockconfig
+ *
+ * Description:
+ * Called to change to new clock based on settings in board.h
+ *
+ * NOTE: This logic would need to be extended if you need to select low-
+ * power clocking modes!
+ ****************************************************************************/
+
+#ifndef CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG
+static void stm32_stdclockconfig(void)
+{
+ uint32_t regval;
+
+ /* If the PLL is using the HSE, or the HSE is the system clock */
+
+#if (STM32_CFGR_PLLSRC == RCC_CFGR_PLLSRC) || (STM32_SYSCLK_SW == RCC_CFGR_SW_HSE)
+
+ {
+ volatile int32_t timeout;
+
+ /* Enable External High-Speed Clock (HSE) */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval &= ~RCC_CR_HSEBYP; /* Disable HSE clock bypass */
+ regval |= RCC_CR_HSEON; /* Enable HSE */
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Wait until the HSE is ready (or until a timeout elapsed) */
+
+ for (timeout = HSERDY_TIMEOUT; timeout > 0; timeout--)
+ {
+ /* Check if the HSERDY flag is the set in the CR */
+
+ if ((getreg32(STM32_RCC_CR) & RCC_CR_HSERDY) != 0)
+ {
+ /* If so, then break-out with timeout > 0 */
+
+ break;
+ }
+ }
+
+ if (timeout == 0)
+ {
+ /* In the case of a timeout starting the HSE, we really don't have a
+ * strategy. This is almost always a hardware failure or misconfiguration.
+ */
+
+ return;
+ }
+ }
+
+ /* If this is a value-line part and we are using the HSE as the PLL */
+
+# if defined(CONFIG_STM32_VALUELINE) && (STM32_CFGR_PLLSRC == RCC_CFGR_PLLSRC)
+
+# if (STM32_CFGR_PLLXTPRE >> 17) != (STM32_CFGR2_PREDIV1 & 1)
+# error STM32_CFGR_PLLXTPRE must match the LSB of STM32_CFGR2_PREDIV1
+# endif
+
+ /* Set the HSE prescaler */
+
+ regval = STM32_CFGR2_PREDIV1;
+ putreg32(regval, STM32_RCC_CFGR2);
+
+# endif
+#endif
+
+ /* Value-line devices don't implement flash prefetch/waitstates */
+
+#ifndef CONFIG_STM32_VALUELINE
+
+ /* Enable FLASH prefetch buffer and 2 wait states */
+
+ regval = getreg32(STM32_FLASH_ACR);
+ regval &= ~FLASH_ACR_LATENCY_MASK;
+ regval |= (FLASH_ACR_LATENCY_2|FLASH_ACR_PRTFBE);
+ putreg32(regval, STM32_FLASH_ACR);
+
+#endif
+
+ /* Set the HCLK source/divider */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_HPRE_MASK;
+ regval |= STM32_RCC_CFGR_HPRE;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Set the PCLK2 divider */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_PPRE2_MASK;
+ regval |= STM32_RCC_CFGR_PPRE2;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Set the PCLK1 divider */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_PPRE1_MASK;
+ regval |= STM32_RCC_CFGR_PPRE1;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* If we are using the PLL, configure and start it */
+
+#if STM32_SYSCLK_SW == RCC_CFGR_SW_PLL
+
+ /* Set the PLL divider and multipler */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~(RCC_CFGR_PLLSRC|RCC_CFGR_PLLXTPRE|RCC_CFGR_PLLMUL_MASK);
+ regval |= (STM32_CFGR_PLLSRC|STM32_CFGR_PLLXTPRE|STM32_CFGR_PLLMUL);
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Enable the PLL */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval |= RCC_CR_PLLON;
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Wait until the PLL is ready */
+
+ while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLRDY) == 0);
+
+#endif
+
+ /* Select the system clock source (probably the PLL) */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_SW_MASK;
+ regval |= STM32_SYSCLK_SW;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Wait until the selected source is used as the system clock source */
+
+ while ((getreg32(STM32_RCC_CFGR) & RCC_CFGR_SWS_MASK) != STM32_SYSCLK_SWS);
+}
+#endif
+
+/****************************************************************************
+ * Name: rcc_enableperiphals
+ ****************************************************************************/
+
+static inline void rcc_enableperipherals(void)
+{
+ rcc_enableahb();
+ rcc_enableapb2();
+ rcc_enableapb1();
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c
new file mode 100644
index 000000000..df8ad9dd5
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c
@@ -0,0 +1,685 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32f10xxx_rtc.c
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With extensions, modifications by:
+ *
+ * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregroy 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.
+ *
+ ************************************************************************************/
+
+/* The STM32 RTC Driver offers standard precision of 1 Hz or High Resolution
+ * operating at rate up to 16384 Hz. It provides UTC time and alarm interface
+ * with external output pin (for wake-up).
+ *
+ * RTC is based on hardware RTC module which is located in a separate power
+ * domain. The 32-bit counter is extended by 16-bit registers in BKP domain
+ * STM32_BKP_DR1 to provide system equiv. function to the: time_t time(time_t *).
+ *
+ * Notation:
+ * - clock refers to 32-bit hardware counter
+ * - time is a combination of clock and upper bits stored in backuped domain
+ * with unit of 1 [s]
+ *
+ * TODO: Error Handling in case LSE fails during start-up or during operation.
+ */
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/rtc.h>
+#include <arch/board/board.h>
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "up_arch.h"
+
+#include "stm32_pwr.h"
+#include "stm32_rcc.h"
+#include "stm32_rtc.h"
+#include "stm32_waste.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* In hi-res mode, the RTC operates at 16384Hz. Overflow interrupts are handled
+ * when the 32-bit RTC counter overflows every 3 days and 43 minutes. A BKP register
+ * is incremented on each overflow interrupt creating, effectively, a 48-bit RTC
+ * counter.
+ *
+ * In the lo-res mode, the RTC operates at 1Hz. Overflow interrupts are not handled
+ * (because the next overflow is not expected until the year 2106.
+ *
+ * WARNING: Overflow interrupts are lost whenever the STM32 is powered down. The
+ * overflow interrupt may be lost even if the STM32 is powered down only momentarily.
+ * Therefor hi-res solution is only useful in systems where the power is always on.
+ */
+
+#ifdef CONFIG_RTC_HIRES
+# ifndef CONFIG_RTC_FREQUENCY
+# error "CONFIG_RTC_FREQUENCY is required for CONFIG_RTC_HIRES"
+# elif CONFIG_RTC_FREQUENCY != 16384
+# error "Only hi-res CONFIG_RTC_FREQUENCY of 16384Hz is supported"
+# endif
+#else
+# ifndef CONFIG_RTC_FREQUENCY
+# define CONFIG_RTC_FREQUENCY 1
+# endif
+# if CONFIG_RTC_FREQUENCY != 1
+# error "Only lo-res CONFIG_RTC_FREQUENCY of 1Hz is supported"
+# endif
+#endif
+
+#ifndef CONFIG_STM32_BKP
+# error "CONFIG_STM32_BKP is required for CONFIG_RTC"
+#endif
+
+/* RTC/BKP Definitions *************************************************************/
+/* STM32_RTC_PRESCALAR_VALUE
+ * RTC pre-scalar value. The RTC is driven by a 32,768Hz input clock. This input
+ * value is divided by this value (plus one) to generate the RTC frequency.
+ * RTC_TIMEMSB_REG
+ * The BKP module register used to hold the RTC overflow value. Overflows are
+ * only handled in hi-res mode.
+ * RTC_CLOCKS_SHIFT
+ * The shift used to convert the hi-res timer LSB to one second. Not used with
+ * the lo-res timer.
+ */
+
+#ifdef CONFIG_RTC_HIRES
+# define STM32_RTC_PRESCALAR_VALUE STM32_RTC_PRESCALER_MIN
+# define RTC_TIMEMSB_REG STM32_BKP_DR1
+# define RTC_CLOCKS_SHIFT 14
+#else
+# define STM32_RTC_PRESCALAR_VALUE STM32_RTC_PRESCALER_SECOND
+#endif
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+
+struct rtc_regvals_s
+{
+ uint16_t cntl;
+ uint16_t cnth;
+#ifdef CONFIG_RTC_HIRES
+ uint16_t ovf;
+#endif
+};
+
+/************************************************************************************
+ * Private Data
+ ************************************************************************************/
+
+/* Callback to use when the alarm expires */
+
+#ifdef CONFIG_RTC_ALARM
+static alarmcb_t g_alarmcb;
+#endif
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/* Variable determines the state of the LSE oscilator.
+ * Possible errors:
+ * - on start-up
+ * - during operation, reported by LSE interrupt
+ */
+
+volatile bool g_rtc_enabled = false;
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: stm32_rtc_beginwr
+ *
+ * Description:
+ * Enter configuration mode
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static inline void stm32_rtc_beginwr(void)
+{
+ /* Previous write is done? */
+
+ while ((getreg16(STM32_RTC_CRL) & RTC_CRL_RTOFF) == 0)
+ {
+ up_waste();
+ }
+
+ /* Enter Config mode, Set Value and Exit */
+
+ modifyreg16(STM32_RTC_CRL, 0, RTC_CRL_CNF);
+}
+
+/************************************************************************************
+ * Name: stm32_rtc_endwr
+ *
+ * Description:
+ * Exit configuration mode
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static inline void stm32_rtc_endwr(void)
+{
+ modifyreg16(STM32_RTC_CRL, RTC_CRL_CNF, 0);
+}
+
+/************************************************************************************
+ * Name: stm32_rtc_wait4rsf
+ *
+ * Description:
+ * Wait for registers to synchronise with RTC module, call after power-up only
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static inline void stm32_rtc_wait4rsf(void)
+{
+ modifyreg16(STM32_RTC_CRL, RTC_CRL_RSF, 0);
+ while ((getreg16(STM32_RTC_CRL) & RTC_CRL_RSF) == 0)
+ {
+ up_waste();
+ }
+}
+
+/************************************************************************************
+ * Name: up_rtc_breakout
+ *
+ * Description:
+ * Set the RTC to the provided time.
+ *
+ * Input Parameters:
+ * tp - the time to use
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_HIRES
+static void up_rtc_breakout(FAR const struct timespec *tp,
+ FAR struct rtc_regvals_s *regvals)
+{
+ uint64_t frac;
+ uint32_t cnt;
+ uint16_t ovf;
+
+ /* Break up the time in seconds + milleconds into the correct values for our use */
+
+ frac = ((uint64_t)tp->tv_nsec * CONFIG_RTC_FREQUENCY) / 1000000000;
+ cnt = (tp->tv_sec << RTC_CLOCKS_SHIFT) | ((uint32_t)frac & (CONFIG_RTC_FREQUENCY-1));
+ ovf = (tp->tv_sec >> (32 - RTC_CLOCKS_SHIFT));
+
+ /* Then return the broken out time */
+
+ regvals->cnth = cnt >> 16;
+ regvals->cntl = cnt & 0xffff;
+ regvals->ovf = ovf;
+}
+#else
+static inline void up_rtc_breakout(FAR const struct timespec *tp,
+ FAR struct rtc_regvals_s *regvals)
+{
+ /* The low-res timer is easy... tv_sec holds exactly the value needed by the
+ * CNTH/CNTL registers.
+ */
+
+ regvals->cnth = (uint16_t)((uint32_t)tp->tv_sec >> 16);
+ regvals->cntl = (uint16_t)((uint32_t)tp->tv_sec & 0xffff);
+}
+#endif
+
+/************************************************************************************
+ * Name: stm32_rtc_interrupt
+ *
+ * Description:
+ * RTC interrupt service routine
+ *
+ * Input Parameters:
+ * irq - The IRQ number that generated the interrupt
+ * context - Architecture specific register save information.
+ *
+ * Returned Value:
+ * Zero (OK) on success; A negated errno value on failure.
+ *
+ ************************************************************************************/
+
+#if defined(CONFIG_RTC_HIRES) || defined(CONFIG_RTC_ALARM)
+static int stm32_rtc_interrupt(int irq, void *context)
+{
+ uint16_t source = getreg16(STM32_RTC_CRL);
+
+#ifdef CONFIG_RTC_HIRES
+ if ((source & RTC_CRL_OWF) != 0)
+ {
+ putreg16(getreg16(RTC_TIMEMSB_REG) + 1, RTC_TIMEMSB_REG);
+ }
+#endif
+
+#ifdef CONFIG_RTC_ALARM
+ if ((source & RTC_CRL_ALRF) != 0 && g_alarmcb != NULL)
+ {
+ /* Alarm callback */
+
+ g_alarmcb();
+ g_alarmcb = NULL;
+ }
+#endif
+
+ /* Clear pending flags, leave RSF high */
+
+ putreg16(RTC_CRL_RSF, STM32_RTC_CRL);
+ return 0;
+}
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_rtcinitialize
+ *
+ * Description:
+ * Initialize the hardware RTC per the selected configuration. This function is
+ * called once during the OS initialization sequence
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtcinitialize(void)
+{
+ /* Set access to the peripheral, enable the backup domain (BKP) and the lower power
+ * extern 32,768Hz (Low-Speed External, LSE) oscillator. Configure the LSE to
+ * drive the RTC.
+ */
+
+ stm32_pwr_enablebkp();
+ stm32_rcc_enablelse();
+
+ /* TODO: Get state from this function, if everything is
+ * okay and whether it is already enabled (if it was disabled
+ * reset upper time register)
+ */
+
+ g_rtc_enabled = true;
+
+ /* TODO: Possible stall? should we set the timeout period? and return with -1 */
+
+ stm32_rtc_wait4rsf();
+
+ /* Configure prescaler, note that these are write-only registers */
+
+ stm32_rtc_beginwr();
+ putreg16(STM32_RTC_PRESCALAR_VALUE >> 16, STM32_RTC_PRLH);
+ putreg16(STM32_RTC_PRESCALAR_VALUE & 0xffff, STM32_RTC_PRLL);
+ stm32_rtc_endwr();
+
+ /* Configure RTC interrupt to catch overflow and alarm interrupts. */
+
+#if defined(CONFIG_RTC_HIRES) || defined(CONFIG_RTC_ALARM)
+ irq_attach(STM32_IRQ_RTC, stm32_rtc_interrupt);
+ up_enable_irq(STM32_IRQ_RTC);
+#endif
+
+ /* Previous write is done? This is required prior writing into CRH */
+
+ while ((getreg16(STM32_RTC_CRL) & RTC_CRL_RTOFF) == 0)
+ {
+ up_waste();
+ }
+ modifyreg16(STM32_RTC_CRH, 0, RTC_CRH_OWIE);
+
+ /* Alarm Int via EXTI Line */
+
+ /* STM32_IRQ_RTCALRM 41: RTC alarm through EXTI line interrupt */
+
+ return OK;
+}
+
+/************************************************************************************
+ * Name: up_rtc_time
+ *
+ * Description:
+ * Get the current time in seconds. This is similar to the standard time()
+ * function. This interface is only required if the low-resolution RTC/counter
+ * hardware implementation selected. It is only used by the RTOS during
+ * intialization to set up the system time when CONFIG_RTC is set but neither
+ * CONFIG_RTC_HIRES nor CONFIG_RTC_DATETIME are set.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * The current time in seconds
+ *
+ ************************************************************************************/
+
+#ifndef CONFIG_RTC_HIRES
+time_t up_rtc_time(void)
+{
+ irqstate_t flags;
+ uint16_t cnth;
+ uint16_t cntl;
+ uint16_t tmp;
+
+ /* The RTC counter is read from two 16-bit registers to form one 32-bit
+ * value. Because these are non-atomic operations, many things can happen
+ * between the two reads: This thread could get suspended or interrrupted
+ * or the lower 16-bit counter could rollover between reads. Disabling
+ * interrupts will prevent suspensions and interruptions:
+ */
+
+ flags = irqsave();
+
+ /* And the following loop will handle any clock rollover events that may
+ * happen between samples. Most of the time (like 99.9%), the following
+ * loop will execute only once. In the rare rollover case, it should
+ * execute no more than 2 times.
+ */
+
+ do
+ {
+ tmp = getreg16(STM32_RTC_CNTL);
+ cnth = getreg16(STM32_RTC_CNTH);
+ cntl = getreg16(STM32_RTC_CNTL);
+ }
+
+ /* The second sample of CNTL could be less than the first sample of CNTL
+ * only if rollover occurred. In that case, CNTH may or may not be out
+ * of sync. The best thing to do is try again until we know that no
+ * rollover occurred.
+ */
+
+ while (cntl < tmp);
+ irqrestore(flags);
+
+ /* Okay.. the samples should be as close together in time as possible and
+ * we can be assured that no clock rollover occurred between the samples.
+ *
+ * Return the time in seconds.
+ */
+
+ return (time_t)cnth << 16 | (time_t)cntl;
+}
+#endif
+
+/************************************************************************************
+ * Name: up_rtc_gettime
+ *
+ * Description:
+ * Get the current time from the high resolution RTC clock/counter. This interface
+ * is only supported by the high-resolution RTC/counter hardware implementation.
+ * It is used to replace the system timer.
+ *
+ * Input Parameters:
+ * tp - The location to return the high resolution time value.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_HIRES
+int up_rtc_gettime(FAR struct timespec *tp)
+{
+ irqstate_t flags;
+ uint32_t ls;
+ uint32_t ms;
+ uint16_t ovf;
+ uint16_t cnth;
+ uint16_t cntl;
+ uint16_t tmp;
+
+ /* The RTC counter is read from two 16-bit registers to form one 32-bit
+ * value. Because these are non-atomic operations, many things can happen
+ * between the two reads: This thread could get suspended or interrrupted
+ * or the lower 16-bit counter could rollover between reads. Disabling
+ * interrupts will prevent suspensions and interruptions:
+ */
+
+ flags = irqsave();
+
+ /* And the following loop will handle any clock rollover events that may
+ * happen between samples. Most of the time (like 99.9%), the following
+ * loop will execute only once. In the rare rollover case, it should
+ * execute no more than 2 times.
+ */
+
+ do
+ {
+ tmp = getreg16(STM32_RTC_CNTL);
+ cnth = getreg16(STM32_RTC_CNTH);
+ ovf = getreg16(RTC_TIMEMSB_REG);
+ cntl = getreg16(STM32_RTC_CNTL);
+ }
+
+ /* The second sample of CNTL could be less than the first sample of CNTL
+ * only if rollover occurred. In that case, CNTH may or may not be out
+ * of sync. The best thing to do is try again until we know that no
+ * rollover occurred.
+ */
+
+ while (cntl < tmp);
+ irqrestore(flags);
+
+ /* Okay.. the samples should be as close together in time as possible and
+ * we can be assured that no clock rollover occurred between the samples.
+ *
+ * Create a 32-bit value from the LS and MS 16-bit RTC counter values and
+ * from the MS and overflow 16-bit counter values.
+ */
+
+ ls = (uint32_t)cnth << 16 | (uint32_t)cntl;
+ ms = (uint32_t)ovf << 16 | (uint32_t)cnth;
+
+ /* Then we can save the time in seconds and fractional seconds. */
+
+ tp->tv_sec = (ms << (32-RTC_CLOCKS_SHIFT-16)) | (ls >> (RTC_CLOCKS_SHIFT+16));
+ tp->tv_nsec = (ls & (CONFIG_RTC_FREQUENCY-1)) * (1000000000/CONFIG_RTC_FREQUENCY);
+ return OK;
+}
+#endif
+
+/************************************************************************************
+ * Name: up_rtc_settime
+ *
+ * Description:
+ * Set the RTC to the provided time. All RTC implementations must be able to
+ * set their time based on a standard timespec.
+ *
+ * Input Parameters:
+ * tp - the time to use
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtc_settime(FAR const struct timespec *tp)
+{
+ struct rtc_regvals_s regvals;
+ irqstate_t flags;
+
+ /* Break out the time values */
+
+ up_rtc_breakout(tp, &regvals);
+
+ /* Then write the broken out values to the RTC counter and BKP overflow register
+ * (hi-res mode only)
+ */
+
+ flags = irqsave();
+ stm32_rtc_beginwr();
+ putreg16(regvals.cnth, STM32_RTC_CNTH);
+ putreg16(regvals.cntl, STM32_RTC_CNTL);
+ stm32_rtc_endwr();
+
+#ifdef CONFIG_RTC_HIRES
+ putreg16(regvals.ovf, RTC_TIMEMSB_REG);
+#endif
+ irqrestore(flags);
+ return OK;
+}
+
+/************************************************************************************
+ * Name: up_rtc_setalarm
+ *
+ * Description:
+ * Set up an alarm.
+ *
+ * Input Parameters:
+ * tp - the time to set the alarm
+ * callback - the function to call when the alarm expires.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
+{
+ struct rtc_regvals_s regvals;
+ irqstate_t flags;
+ uint16_t cr;
+ int ret = -EBUSY;
+
+ /* Is there already something waiting on the ALARM? */
+
+ if (g_alarmcb == NULL)
+ {
+ /* No.. Save the callback function pointer */
+
+ g_alarmcb = callback;
+
+ /* Break out the time values */
+
+ up_rtc_breakout(tp, &regvals);
+
+ /* Enable RTC alarm */
+
+ cr = getreg16(STM32_RTC_CRH);
+ cr |= RTC_CRH_ALRIE;
+ putreg16(cr, STM32_RTC_CRH);
+
+ /* The set the alarm */
+
+ flags = irqsave();
+ stm32_rtc_beginwr();
+ putreg16(regvals.cnth, STM32_RTC_ALRH);
+ putreg16(regvals.cntl, STM32_RTC_ALRL);
+ stm32_rtc_endwr();
+ irqrestore(flags);
+
+ ret = OK;
+ }
+ return ret;
+}
+#endif
+
+/************************************************************************************
+ * Name: up_rtc_cancelalarm
+ *
+ * Description:
+ * Cancel a pending alarm alarm
+ *
+ * Input Parameters:
+ * none
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+int up_rtc_cancelalarm(void)
+{
+ irqstate_t flags;
+ int ret = -ENODATA;
+
+ if (g_alarmcb != NULL)
+ {
+ /* Cancel the global callback function */
+
+ g_alarmcb = NULL;
+
+ /* Unset the alarm */
+
+ flags = irqsave();
+ stm32_rtc_beginwr();
+ putreg16(0xffff, STM32_RTC_ALRH);
+ putreg16(0xffff, STM32_RTC_ALRL);
+ stm32_rtc_endwr();
+ irqrestore(flags);
+
+ ret = OK;
+ }
+ return ret;
+}
+#endif
diff --git a/nuttx/arch/arm/src/stm32/stm32f20xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f20xxx_dma.c
new file mode 100644
index 000000000..7e3ece2fa
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32f20xxx_dma.c
@@ -0,0 +1,903 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32f20xxx_dma.c
+ *
+ * Copyright (C) 2012 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 <stdbool.h>
+#include <semaphore.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/irq.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+#include "os_internal.h"
+#include "chip.h"
+#include "stm32_dma.h"
+#include "stm32_internal.h"
+
+/* This file supports only the STM32 F2 family (although it is identical to
+ * the corresponding F4 file).
+ */
+
+#if defined(CONFIG_STM32_STM32F20XX)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DMA1_NSTREAMS 8
+#if STM32_NDMA > 1
+# define DMA2_NSTREAMS 8
+# define DMA_NSTREAMS (DMA1_NSTREAMS+DMA2_NSTREAMS)
+#else
+# define DMA_NSTREAMS DMA1_NSTREAMS
+#endif
+
+#ifndef CONFIG_DMA_PRI
+# define CONFIG_DMA_PRI NVIC_SYSH_PRIORITY_DEFAULT
+#endif
+
+/* Convert the DMA stream base address to the DMA register block address */
+
+#define DMA_BASE(ch) (ch & 0xfffffc00)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure descibes one DMA channel */
+
+struct stm32_dma_s
+{
+ uint8_t stream; /* DMA stream number (0-7) */
+ uint8_t irq; /* DMA stream IRQ number */
+ uint8_t shift; /* ISR/IFCR bit shift value */
+ uint8_t channel; /* DMA channel number (0-7) */
+ bool nonstop; /* Stream is configured in a non-stopping mode. */
+ sem_t sem; /* Used to wait for DMA channel to become available */
+ uint32_t base; /* DMA register channel base address */
+ dma_callback_t callback; /* Callback invoked when the DMA completes */
+ void *arg; /* Argument passed to callback function */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This array describes the state of each DMA */
+
+static struct stm32_dma_s g_dma[DMA_NSTREAMS] =
+{
+ {
+ .stream = 0,
+ .irq = STM32_IRQ_DMA1S0,
+ .shift = DMA_INT_STREAM0_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(0),
+ },
+ {
+ .stream = 1,
+ .irq = STM32_IRQ_DMA1S1,
+ .shift = DMA_INT_STREAM1_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(1),
+ },
+ {
+ .stream = 2,
+ .irq = STM32_IRQ_DMA1S2,
+ .shift = DMA_INT_STREAM2_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(2),
+ },
+ {
+ .stream = 3,
+ .irq = STM32_IRQ_DMA1S3,
+ .shift = DMA_INT_STREAM3_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(4),
+ },
+ {
+ .stream = 4,
+ .irq = STM32_IRQ_DMA1S4,
+ .shift = DMA_INT_STREAM4_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(4),
+ },
+ {
+ .stream = 5,
+ .irq = STM32_IRQ_DMA1S5,
+ .shift = DMA_INT_STREAM5_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(5),
+ },
+ {
+ .stream = 6,
+ .irq = STM32_IRQ_DMA1S6,
+ .shift = DMA_INT_STREAM6_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(6),
+ },
+ {
+ .stream = 7,
+ .irq = STM32_IRQ_DMA1S7,
+ .shift = DMA_INT_STREAM7_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(7),
+ },
+#if STM32_NDMA > 1
+ {
+ .stream = 0,
+ .irq = STM32_IRQ_DMA2S0,
+ .shift = DMA_INT_STREAM0_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(0),
+ },
+ {
+ .stream = 1,
+ .irq = STM32_IRQ_DMA2S1,
+ .shift = DMA_INT_STREAM1_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(1),
+ },
+ {
+ .stream = 2,
+ .irq = STM32_IRQ_DMA2S2,
+ .shift = DMA_INT_STREAM2_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(2),
+ },
+ {
+ .stream = 3,
+ .irq = STM32_IRQ_DMA2S3,
+ .shift = DMA_INT_STREAM3_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(3),
+ },
+ {
+ .stream = 4,
+ .irq = STM32_IRQ_DMA2S4,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(4),
+ },
+ {
+ .stream = 5,
+ .irq = STM32_IRQ_DMA2S5,
+ .shift = DMA_INT_STREAM5_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(5),
+ },
+ {
+ .stream = 6,
+ .irq = STM32_IRQ_DMA2S6,
+ .shift = DMA_INT_STREAM6_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(6),
+ },
+ {
+ .stream = 7,
+ .irq = STM32_IRQ_DMA2S7,
+ .shift = DMA_INT_STREAM7_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(7),
+ },
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * DMA register access functions
+ ****************************************************************************/
+
+/* Get non-channel register from DMA1 or DMA2 */
+
+static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmast, uint32_t offset)
+{
+ return getreg32(DMA_BASE(dmast->base) + offset);
+}
+
+/* Write to non-channel register in DMA1 or DMA2 */
+
+static inline void dmabase_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value)
+{
+ putreg32(value, DMA_BASE(dmast->base) + offset);
+}
+
+/* Get channel register from DMA1 or DMA2 */
+
+static inline uint32_t dmast_getreg(struct stm32_dma_s *dmast, uint32_t offset)
+{
+ return getreg32(dmast->base + offset);
+}
+
+/* Write to channel register in DMA1 or DMA2 */
+
+static inline void dmast_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value)
+{
+ putreg32(value, dmast->base + offset);
+}
+
+/************************************************************************************
+ * Name: stm32_dmatake() and stm32_dmagive()
+ *
+ * Description:
+ * Used to get exclusive access to a DMA channel.
+ *
+ ************************************************************************************/
+
+static void stm32_dmatake(FAR struct stm32_dma_s *dmast)
+{
+ /* Take the semaphore (perhaps waiting) */
+
+ while (sem_wait(&dmast->sem) != 0)
+ {
+ /* The only case that an error should occur here is if the wait was awakened
+ * by a signal.
+ */
+
+ ASSERT(errno == EINTR);
+ }
+}
+
+static inline void stm32_dmagive(FAR struct stm32_dma_s *dmast)
+{
+ (void)sem_post(&dmast->sem);
+}
+
+/************************************************************************************
+ * Name: stm32_dmastream
+ *
+ * Description:
+ * Get the g_dma table entry associated with a DMA controller and a stream number
+ *
+ ************************************************************************************/
+
+static inline FAR struct stm32_dma_s *stm32_dmastream(unsigned int stream,
+ unsigned int controller)
+{
+ int index;
+
+ DEBUGASSERT(stream < DMA_NSTREAMS && controller < STM32_NDMA);
+
+ /* Convert the controller + stream based on the fact that there are 8 streams
+ * per controller.
+ */
+
+#if STM32_NDMA > 1
+ index = controller << 3 | stream;
+#else
+ index = stream;
+#endif
+
+ /* Then return the stream structure associated with the stream index */
+
+ return &g_dma[index];
+}
+
+/************************************************************************************
+ * Name: stm32_dmamap
+ *
+ * Description:
+ * Get the g_dma table entry associated with a bit-encoded DMA selection
+ *
+ ************************************************************************************/
+
+static inline FAR struct stm32_dma_s *stm32_dmamap(unsigned long dmamap)
+{
+ /* Extract the DMA controller number from the bit encoded value */
+
+ unsigned int controller = STM32_DMA_CONTROLLER(dmamap);
+
+ /* Extact the stream number from the bit encoded value */
+
+ unsigned int stream = STM32_DMA_STREAM(dmamap);
+
+ /* Return the table entry associated with the controller + stream */
+
+ return stm32_dmastream(stream, controller);
+}
+
+/************************************************************************************
+ * Name: stm32_dmastreamdisable
+ *
+ * Description:
+ * Disable the DMA stream
+ *
+ ************************************************************************************/
+
+static void stm32_dmastreamdisable(struct stm32_dma_s *dmast)
+{
+ uint32_t regoffset;
+ uint32_t regval;
+
+ /* Disable all interrupts at the DMA controller */
+
+ regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ regval &= ~DMA_SCR_ALLINTS;
+
+ /* Disable the DMA stream */
+
+ regval &= ~DMA_SCR_EN;
+ dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
+
+ /* Clear pending stream interrupts by setting bits in the upper or lower IFCR
+ * register
+ */
+
+ if (dmast->stream < 4)
+ {
+ regoffset = STM32_DMA_LIFCR_OFFSET;
+ }
+ else
+ {
+ regoffset = STM32_DMA_HIFCR_OFFSET;
+ }
+
+ dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift));
+}
+
+/************************************************************************************
+ * Name: stm32_dmainterrupt
+ *
+ * Description:
+ * DMA interrupt handler
+ *
+ ************************************************************************************/
+
+static int stm32_dmainterrupt(int irq, void *context)
+{
+ struct stm32_dma_s *dmast;
+ uint32_t status;
+ uint32_t regoffset = 0;
+ unsigned int stream = 0;
+ unsigned int controller = 0;
+
+ /* Get the stream and the controller that generated the interrupt */
+
+ if (irq >= STM32_IRQ_DMA1S0 && irq <= STM32_IRQ_DMA1S6)
+ {
+ stream = irq - STM32_IRQ_DMA1S0;
+ controller = DMA1;
+ }
+ else if (irq == STM32_IRQ_DMA1S7)
+ {
+ stream = 7;
+ controller = DMA1;
+ }
+ else
+#if STM32_NDMA > 1
+ if (irq >= STM32_IRQ_DMA2S0 && irq <= STM32_IRQ_DMA2S4)
+ {
+ stream = irq - STM32_IRQ_DMA2S0;
+ controller = DMA2;
+ }
+ else if (irq >= STM32_IRQ_DMA2S5 && irq <= STM32_IRQ_DMA2S7)
+ {
+ stream = irq - STM32_IRQ_DMA2S5 + 5;
+ controller = DMA2;
+ }
+ else
+#endif
+ {
+ PANIC(OSERR_INTERNAL);
+ }
+
+ /* Get the stream structure from the stream and controller numbers */
+
+ dmast = stm32_dmastream(stream, controller);
+
+ /* Select the interrupt status register (either the LISR or HISR)
+ * based on the stream number that caused the interrupt.
+ */
+
+ if (stream < 4)
+ {
+ regoffset = STM32_DMA_LISR_OFFSET;
+ }
+ else
+ {
+ regoffset = STM32_DMA_HISR_OFFSET;
+ }
+
+ /* Get the interrupt status for this stream */
+
+ status = (dmabase_getreg(dmast, regoffset) >> dmast->shift) & DMA_STREAM_MASK;
+
+ /* Clear fetched stream interrupts by setting bits in the upper or lower IFCR
+ * register
+ */
+
+ if (stream < 4)
+ {
+ regoffset = STM32_DMA_LIFCR_OFFSET;
+ }
+ else
+ {
+ regoffset = STM32_DMA_HIFCR_OFFSET;
+ }
+
+ dmabase_putreg(dmast, regoffset, (status << dmast->shift));
+
+ /* Invoke the callback */
+
+ if (dmast->callback)
+ {
+ dmast->callback(dmast, status, dmast->arg);
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_dmainitialize
+ *
+ * Description:
+ * Initialize the DMA subsystem
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void weak_function up_dmainitialize(void)
+{
+ struct stm32_dma_s *dmast;
+ int stream;
+
+ /* Initialize each DMA stream */
+
+ for (stream = 0; stream < DMA_NSTREAMS; stream++)
+ {
+ dmast = &g_dma[stream];
+ sem_init(&dmast->sem, 0, 1);
+
+ /* Attach DMA interrupt vectors */
+
+ (void)irq_attach(dmast->irq, stm32_dmainterrupt);
+
+ /* Disable the DMA stream */
+
+ stm32_dmastreamdisable(dmast);
+
+ /* Enable the IRQ at the NVIC (still disabled at the DMA controller) */
+
+ up_enable_irq(dmast->irq);
+
+ /* Set the interrrupt priority */
+
+ up_prioritize_irq(dmast->irq, CONFIG_DMA_PRI);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_dmachannel
+ *
+ * Description:
+ * Allocate a DMA channel. This function gives the caller mutually
+ * exclusive access to the DMA channel specified by the 'dmamap' argument.
+ * DMA channels are shared on the STM32: Devices sharing the same DMA
+ * channel cannot do DMA concurrently! See the DMACHAN_* definitions in
+ * stm32_dma.h.
+ *
+ * If the DMA channel is not available, then stm32_dmachannel() will wait
+ * until the holder of the channel relinquishes the channel by calling
+ * stm32_dmafree(). WARNING: If you have two devices sharing a DMA
+ * channel and the code never releases the channel, the stm32_dmachannel
+ * call for the other will hang forever in this function! Don't let your
+ * design do that!
+ *
+ * Hmm.. I suppose this interface could be extended to make a non-blocking
+ * version. Feel free to do that if that is what you need.
+ *
+ * Input parameter:
+ * dmamap - Identifies the stream/channel resource. For the STM32 F2, this
+ * is a bit-encoded value as provided by the the DMAMAP_* definitions
+ * in chip/stm32f20xxx_dma.h
+ *
+ * Returned Value:
+ * Provided that 'dmamap' is valid, this function ALWAYS returns a non-NULL,
+ * void* DMA channel handle. (If 'dmamap' is invalid, the function will
+ * assert if debug is enabled or do something ignorant otherwise).
+ *
+ * Assumptions:
+ * - The caller does not hold he DMA channel.
+ * - The caller can wait for the DMA channel to be freed if it is no
+ * available.
+ *
+ ****************************************************************************/
+
+DMA_HANDLE stm32_dmachannel(unsigned int dmamap)
+{
+ FAR struct stm32_dma_s *dmast;
+
+ /* Get the stream index from the bit-encoded channel value */
+
+ dmast = stm32_dmamap(dmamap);
+ DEBUGASSERT(dmast != NULL);
+
+ /* Get exclusive access to the DMA channel -- OR wait until the channel
+ * is available if it is currently being used by another driver
+ */
+
+ stm32_dmatake(dmast);
+
+ /* The caller now has exclusive use of the DMA channel. Assign the
+ * channel to the stream and return an opaque reference to the stream
+ * structure.
+ */
+
+ dmast->channel = STM32_DMA_CHANNEL(dmamap);
+ return (DMA_HANDLE)dmast;
+}
+
+/****************************************************************************
+ * Name: stm32_dmafree
+ *
+ * Description:
+ * Release a DMA channel. If another thread is waiting for this DMA channel
+ * in a call to stm32_dmachannel, then this function will re-assign the
+ * DMA channel to that thread and wake it up. NOTE: The 'handle' used
+ * in this argument must NEVER be used again until stm32_dmachannel() is
+ * called again to re-gain access to the channel.
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * - The caller holds the DMA channel.
+ * - There is no DMA in progress
+ *
+ ****************************************************************************/
+
+void stm32_dmafree(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+
+ DEBUGASSERT(handle != NULL);
+
+ /* Release the channel */
+
+ stm32_dmagive(dmast);
+}
+
+/****************************************************************************
+ * Name: stm32_dmasetup
+ *
+ * Description:
+ * Configure DMA before using
+ *
+ ****************************************************************************/
+
+void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
+ size_t ntransfers, uint32_t scr)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ uint32_t regoffset;
+ uint32_t regval;
+
+ dmadbg("paddr: %08x maddr: %08x ntransfers: %d scr: %08x\n",
+ paddr, maddr, ntransfers, scr);
+
+ /* "If the stream is enabled, disable it by resetting the EN bit in the
+ * DMA_SxCR register, then read this bit in order to confirm that there is no
+ * ongoing stream operation. Writing this bit to 0 is not immediately
+ * effective since it is actually written to 0 once all the current transfers
+ * have finished. When the EN bit is read as 0, this means that the stream is
+ * ready to be configured. It is therefore necessary to wait for the EN bit
+ * to be cleared before starting any stream configuration. ..."
+ */
+
+ while ((dmast_getreg(dmast, STM32_DMA_SCR_OFFSET) & DMA_SCR_EN) != 0);
+
+ /* "... All the stream dedicated bits set in the status register (DMA_LISR
+ * and DMA_HISR) from the previous data block DMA transfer should be cleared
+ * before the stream can be re-enabled."
+ *
+ * Clear pending stream interrupts by setting bits in the upper or lower IFCR
+ * register
+ */
+
+ if (dmast->stream < 4)
+ {
+ regoffset = STM32_DMA_LIFCR_OFFSET;
+ }
+ else
+ {
+ regoffset = STM32_DMA_HIFCR_OFFSET;
+ }
+
+ dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift));
+
+ /* "Set the peripheral register address in the DMA_SPARx register. The data
+ * will be moved from/to this address to/from the memory after the
+ * peripheral event.
+ */
+
+ dmast_putreg(dmast, STM32_DMA_SPAR_OFFSET, paddr);
+
+ /* "Set the memory address in the DMA_SM0ARx ... register. The data will be
+ * written to or read from this memory after the peripheral event."
+ *
+ * Note that in double-buffered mode it is explicitly assumed that the second
+ * buffer immediately follows the first.
+ */
+
+ dmast_putreg(dmast, STM32_DMA_SM0AR_OFFSET, maddr);
+ if (scr & DMA_SCR_DBM)
+ {
+ dmast_putreg(dmast, STM32_DMA_SM1AR_OFFSET, maddr + ntransfers);
+ }
+
+ /* "Configure the total number of data items to be transferred in the
+ * DMA_SNDTRx register. After each peripheral event, this value will be
+ * decremented."
+ *
+ * "When the peripheral flow controller is used for a given stream, the value
+ * written into the DMA_SxNDTR has no effect on the DMA transfer. Actually,
+ * whatever the value written, it will be forced by hardware to 0xFFFF as soon
+ * as the stream is enabled..."
+ */
+
+ dmast_putreg(dmast, STM32_DMA_SNDTR_OFFSET, ntransfers);
+
+ /* "Select the DMA channel (request) using CHSEL[2:0] in the DMA_SxCR register."
+ *
+ * "Configure the stream priority using the PL[1:0] bits in the DMA_SCRx"
+ * register."
+ */
+
+ regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ regval &= ~(DMA_SCR_PL_MASK|DMA_SCR_CHSEL_MASK);
+ regval |= scr & DMA_SCR_PL_MASK;
+ regval |= (uint32_t)dmast->channel << DMA_SCR_CHSEL_SHIFT;
+ dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
+
+ /* "Configure the FIFO usage (enable or disable, threshold in transmission and
+ * reception)"
+ *
+ * "Caution is required when choosing the FIFO threshold (bits FTH[1:0] of the
+ * DMA_SxFCR register) and the size of the memory burst (MBURST[1:0] of the
+ * DMA_SxCR register): The content pointed by the FIFO threshold must exactly
+ * match to an integer number of memory burst transfers. If this is not in the
+ * case, a FIFO error (flag FEIFx of the DMA_HISR or DMA_LISR register) will be
+ * generated when the stream is enabled, then the stream will be automatically
+ * disabled."
+ *
+ * The FIFO is disabled in circular mode when transferring data from a
+ * peripheral to memory, as in this case it is usually desirable to know that
+ * every byte from the peripheral is transferred immediately to memory. It is
+ * not practical to flush the DMA FIFO, as this requires disabling the channel
+ * which triggers the transfer-complete interrupt.
+ *
+ * NOTE: The FEIFx error interrupt is not enabled because the FEIFx seems to
+ * be reported spuriously causing good transfers to be marked as failures.
+ */
+
+ regval = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET);
+ regval &= ~(DMA_SFCR_FTH_MASK | DMA_SFCR_FS_MASK | DMA_SFCR_FEIE);
+ if (!((scr & (DMA_SCR_CIRC | DMA_SCR_DIR_MASK)) == (DMA_SCR_CIRC | DMA_SCR_DIR_P2M)))
+ {
+ regval |= (DMA_SFCR_FTH_FULL | DMA_SFCR_DMDIS);
+ }
+ dmast_putreg(dmast, STM32_DMA_SFCR_OFFSET, regval);
+
+ /* "Configure data transfer direction, circular mode, peripheral & memory
+ * incremented mode, peripheral & memory data size, and interrupt after
+ * half and/or full transfer in the DMA_CCRx register."
+ *
+ * Note: The CT bit is always reset.
+ */
+
+ regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ regval &= ~(DMA_SCR_PFCTRL|DMA_SCR_DIR_MASK|DMA_SCR_PINC|DMA_SCR_MINC|
+ DMA_SCR_PSIZE_MASK|DMA_SCR_MSIZE_MASK|DMA_SCR_PINCOS|
+ DMA_SCR_CIRC|DMA_SCR_DBM|DMA_SCR_CT|
+ DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK);
+ scr &= (DMA_SCR_PFCTRL|DMA_SCR_DIR_MASK|DMA_SCR_PINC|DMA_SCR_MINC|
+ DMA_SCR_PSIZE_MASK|DMA_SCR_MSIZE_MASK|DMA_SCR_PINCOS|
+ DMA_SCR_DBM|DMA_SCR_CIRC|
+ DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK);
+ regval |= scr;
+ dmast->nonstop = (scr & (DMA_SCR_DBM|DMA_SCR_CIRC)) != 0;
+ dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: stm32_dmastart
+ *
+ * Description:
+ * Start the DMA transfer
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ * - No DMA in progress
+ *
+ ****************************************************************************/
+
+void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool half)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ uint32_t scr;
+
+ DEBUGASSERT(handle != NULL);
+
+ /* Save the callback info. This will be invoked whent the DMA commpletes */
+
+ dmast->callback = callback;
+ dmast->arg = arg;
+
+ /* Activate the stream by setting the ENABLE bit in the DMA_SCRx register.
+ * As soon as the stream is enabled, it can serve any DMA request from the
+ * peripheral connected on the stream.
+ */
+
+ scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ scr |= DMA_SCR_EN;
+
+ if (!dmast->nonstop)
+ {
+ /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
+ * set and an interrupt is generated if the Half-Transfer Interrupt Enable
+ * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
+ * (TCIF) is set and an interrupt is generated if the Transfer Complete
+ * Interrupt Enable bit (TCIE) is set.
+ */
+
+ scr |= (half ? (DMA_SCR_HTIE|DMA_SCR_TEIE) : (DMA_SCR_TCIE|DMA_SCR_TEIE));
+ }
+ else
+ {
+ /* In nonstop mode, when the transfer completes it immediately resets
+ * and starts again. The transfer-complete interrupt is thus always
+ * enabled, and the half-complete interrupt can be used in circular
+ * mode to determine when the buffer is half-full, or in double-buffered
+ * mode to determine when one of the two buffers is full.
+ */
+ scr |= (half ? DMA_SCR_HTIE : 0) | DMA_SCR_TCIE | DMA_SCR_TEIE;
+ }
+
+ dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, scr);
+}
+
+/****************************************************************************
+ * Name: stm32_dmastop
+ *
+ * Description:
+ * Cancel the DMA. After stm32_dmastop() is called, the DMA channel is
+ * reset and stm32_dmasetup() must be called before stm32_dmastart() can be
+ * called again
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+void stm32_dmastop(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ stm32_dmastreamdisable(dmast);
+}
+
+/****************************************************************************
+ * Name: stm32_dmaresidual
+ *
+ * Description:
+ * Read the DMA bytes-remaining register.
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+size_t stm32_dmaresidual(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ uint32_t residual;
+
+ /* Fetch the count of bytes remaining to be transferred.
+ *
+ * If the FIFO is enabled, this count may be inaccurate. ST don't
+ * appear to document whether this counts the peripheral or the memory
+ * side of the channel, and they don't make the memory pointer
+ * available either.
+ *
+ * For reception in circular mode the FIFO is disabled in order that
+ * this value can be useful.
+ */
+
+ residual = dmast_getreg(dmast, STM32_DMA_SNDTR_OFFSET);
+
+ return (size_t)residual;
+}
+
+/****************************************************************************
+ * Name: stm32_dmasample
+ *
+ * Description:
+ * Sample DMA register contents
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_DMA
+void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ irqstate_t flags;
+
+ flags = irqsave();
+ regs->lisr = dmabase_getreg(dmast, STM32_DMA_LISR_OFFSET);
+ regs->hisr = dmabase_getreg(dmast, STM32_DMA_HISR_OFFSET);
+ regs->scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ regs->sndtr = dmast_getreg(dmast, STM32_DMA_SNDTR_OFFSET);
+ regs->spar = dmast_getreg(dmast, STM32_DMA_SPAR_OFFSET);
+ regs->sm0ar = dmast_getreg(dmast, STM32_DMA_SM0AR_OFFSET);
+ regs->sm1ar = dmast_getreg(dmast, STM32_DMA_SM1AR_OFFSET);
+ regs->sfcr = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET);
+ irqrestore(flags);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_dmadump
+ *
+ * Description:
+ * Dump previously sampled DMA register contents
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_DMA
+void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs,
+ const char *msg)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ uint32_t dmabase = DMA_BASE(dmast->base);
+
+ dmadbg("DMA Registers: %s\n", msg);
+ dmadbg(" LISR[%08x]: %08x\n", dmabase + STM32_DMA_LISR_OFFSET, regs->lisr);
+ dmadbg(" HISR[%08x]: %08x\n", dmabase + STM32_DMA_HISR_OFFSET, regs->hisr);
+ dmadbg(" SCR[%08x]: %08x\n", dmast->base + STM32_DMA_SCR_OFFSET, regs->scr);
+ dmadbg(" SNDTR[%08x]: %08x\n", dmast->base + STM32_DMA_SNDTR_OFFSET, regs->sndtr);
+ dmadbg(" SPAR[%08x]: %08x\n", dmast->base + STM32_DMA_SPAR_OFFSET, regs->spar);
+ dmadbg(" SM0AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM0AR_OFFSET, regs->sm0ar);
+ dmadbg(" SM1AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM1AR_OFFSET, regs->sm1ar);
+ dmadbg(" SFCR[%08x]: %08x\n", dmast->base + STM32_DMA_SFCR_OFFSET, regs->sfcr);
+}
+#endif
+
+#endif /* CONFIG_STM32_STM32F20XX */
diff --git a/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c
new file mode 100644
index 000000000..8cfd405de
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32f20xxx_rcc.c
@@ -0,0 +1,666 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32f20xxx_rcc.c
+ *
+ * Copyright (C) 2012 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 "stm32_pwr.h"
+
+/* This file supports only the STM32 F2 family (although it is identical to
+ * the corresponding F4 file).
+ */
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* Allow up to 100 milliseconds for the high speed clock to become ready.
+ * that is a very long delay, but if the clock does not become ready we are
+ * hosed anyway. Normally this is very fast, but I have seen at least one
+ * board that required this long, long timeout for the HSE to be ready.
+ */
+
+#define HSERDY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rcc_reset
+ *
+ * Description:
+ * Reset the RCC clock configuration to the default reset state
+ *
+ ****************************************************************************/
+
+static inline void rcc_reset(void)
+{
+ uint32_t regval;
+
+ /* Enable the Internal High Speed clock (HSI) */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval |= RCC_CR_HSION;
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Reset CFGR register */
+
+ putreg32(0x00000000, STM32_RCC_CFGR);
+
+ /* Reset HSEON, CSSON and PLLON bits */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval &= ~(RCC_CR_HSEON|RCC_CR_CSSON|RCC_CR_PLLON);
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Reset PLLCFGR register to reset default */
+
+ putreg32(RCC_PLLCFG_RESET, STM32_RCC_PLLCFG);
+
+ /* Reset HSEBYP bit */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval &= ~RCC_CR_HSEBYP;
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Disable all interrupts */
+
+ putreg32(0x00000000, STM32_RCC_CIR);
+}
+
+/****************************************************************************
+ * Name: rcc_enableahb1
+ *
+ * Description:
+ * Enable selected AHB1 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableahb1(void)
+{
+ uint32_t regval;
+
+ /* Set the appropriate bits in the AHB1ENR register to enabled the
+ * selected AHB1 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_AHB1ENR);
+
+ /* Enable GPIOA, GPIOB, .... GPIOI*/
+
+#if STM32_NGPIO > 0
+ regval |= (RCC_AHB1ENR_GPIOAEN
+#if STM32_NGPIO > 16
+ |RCC_AHB1ENR_GPIOBEN
+#endif
+#if STM32_NGPIO > 32
+ |RCC_AHB1ENR_GPIOCEN
+#endif
+#if STM32_NGPIO > 48
+ |RCC_AHB1ENR_GPIODEN
+#endif
+#if STM32_NGPIO > 64
+ |RCC_AHB1ENR_GPIOEEN
+#endif
+#if STM32_NGPIO > 80
+ |RCC_AHB1ENR_GPIOFEN
+#endif
+#if STM32_NGPIO > 96
+ |RCC_AHB1ENR_GPIOGEN
+#endif
+#if STM32_NGPIO > 112
+ |RCC_AHB1ENR_GPIOHEN
+#endif
+#if STM32_NGPIO > 128
+ |RCC_AHB1ENR_GPIOIEN
+#endif
+ );
+#endif
+
+#ifdef CONFIG_STM32_CRC
+ /* CRC clock enable */
+
+ regval |= RCC_AHB1ENR_CRCEN;
+#endif
+
+#ifdef CONFIG_STM32_BKPSRAM
+ /* Backup SRAM clock enable */
+
+ regval |= RCC_AHB1ENR_BKPSRAMEN;
+#endif
+
+#ifdef CONFIG_STM32_DMA1
+ /* DMA 1 clock enable */
+
+ regval |= RCC_AHB1ENR_DMA1EN;
+#endif
+
+#ifdef CONFIG_STM32_DMA2
+ /* DMA 2 clock enable */
+
+ regval |= RCC_AHB1ENR_DMA2EN;
+#endif
+
+#ifdef CONFIG_STM32_ETHMAC
+ /* Ethernet MAC clocking */
+
+ regval |= (RCC_AHB1ENR_ETHMACEN|RCC_AHB1ENR_ETHMACTXEN|RCC_AHB1ENR_ETHMACRXEN);
+
+#ifdef CONFIG_STM32_ETH_PTP
+ /* Precision Time Protocol (PTP) */
+
+ regval |= RCC_AHB1ENR_ETHMACPTPEN;
+
+#endif
+#endif
+
+#ifdef CONFIG_STM32_OTGHS
+ /* USB OTG HS */
+
+ regval |= (RCC_AHB1ENR_OTGHSEN|RCC_AHB1ENR_OTGHSULPIEN);
+#endif
+
+ putreg32(regval, STM32_RCC_AHB1ENR); /* Enable peripherals */
+}
+
+/****************************************************************************
+ * Name: rcc_enableahb2
+ *
+ * Description:
+ * Enable selected AHB2 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableahb2(void)
+{
+ uint32_t regval;
+
+ /* Set the appropriate bits in the AHB2ENR register to enabled the
+ * selected AHB2 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_AHB2ENR);
+
+#ifdef CONFIG_STM32_DCMI
+ /* Camera interface enable */
+
+ regval |= RCC_AHB2ENR_DCMIEN;
+#endif
+
+#ifdef CONFIG_STM32_CRYP
+ /* Cryptographic modules clock enable */
+
+ regval |= RCC_AHB2ENR_CRYPEN;
+#endif
+
+#ifdef CONFIG_STM32_HASH
+ /* Hash modules clock enable */
+
+ regval |= RCC_AHB2ENR_HASHEN;
+#endif
+
+#ifdef CONFIG_STM32_RNG
+ /* Random number generator clock enable */
+
+ regval |= RCC_AHB2ENR_RNGEN;
+#endif
+
+#ifdef CONFIG_STM32_OTGFS
+ /* USB OTG FS clock enable */
+
+ regval |= RCC_AHB2ENR_OTGFSEN;
+#endif
+
+ putreg32(regval, STM32_RCC_AHB2ENR); /* Enable peripherals */
+}
+
+/****************************************************************************
+ * Name: rcc_enableahb3
+ *
+ * Description:
+ * Enable selected AHB3 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableahb3(void)
+{
+#ifdef CONFIG_STM32_FSMC
+ uint32_t regval;
+
+ /* Set the appropriate bits in the AHB3ENR register to enabled the
+ * selected AHB3 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_AHB3ENR);
+
+ /* Flexible static memory controller module clock enable */
+
+ regval |= RCC_AHB3ENR_FSMCEN;
+
+ putreg32(regval, STM32_RCC_AHB3ENR); /* Enable peripherals */
+#endif
+}
+
+/****************************************************************************
+ * Name: rcc_enableapb1
+ *
+ * Description:
+ * Enable selected APB1 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableapb1(void)
+{
+ uint32_t regval;
+
+ /* Set the appropriate bits in the APB1ENR register to enabled the
+ * selected APB1 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_APB1ENR);
+
+#ifdef CONFIG_STM32_TIM2
+ /* TIM2 clock enable */
+
+ regval |= RCC_APB1ENR_TIM2EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM3
+ /* TIM3 clock enable */
+
+ regval |= RCC_APB1ENR_TIM3EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM4
+ /* TIM4 clock enable */
+
+ regval |= RCC_APB1ENR_TIM4EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM5
+ /* TIM5 clock enable */
+
+ regval |= RCC_APB1ENR_TIM5EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM6
+ /* TIM6 clock enable */
+
+ regval |= RCC_APB1ENR_TIM6EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM7
+ /* TIM7 clock enable */
+
+ regval |= RCC_APB1ENR_TIM7EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM12
+ /* TIM12 clock enable */
+
+ regval |= RCC_APB1ENR_TIM12EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM13
+ /* TIM13 clock enable */
+
+ regval |= RCC_APB1ENR_TIM13EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM14
+ /* TIM14 clock enable */
+
+ regval |= RCC_APB1ENR_TIM14EN;
+#endif
+
+#ifdef CONFIG_STM32_WWDG
+ /* Window watchdog clock enable */
+
+ regval |= RCC_APB1ENR_WWDGEN;
+#endif
+
+#ifdef CONFIG_STM32_SPI2
+ /* SPI2 clock enable */
+
+ regval |= RCC_APB1ENR_SPI2EN;
+#endif
+
+#ifdef CONFIG_STM32_SPI3
+ /* SPI3 clock enable */
+
+ regval |= RCC_APB1ENR_SPI3EN;
+#endif
+
+#ifdef CONFIG_STM32_USART2
+ /* USART 2 clock enable */
+
+ regval |= RCC_APB1ENR_USART2EN;
+#endif
+
+#ifdef CONFIG_STM32_USART3
+ /* USART3 clock enable */
+
+ regval |= RCC_APB1ENR_USART3EN;
+#endif
+
+#ifdef CONFIG_STM32_UART4
+ /* UART4 clock enable */
+
+ regval |= RCC_APB1ENR_UART4EN;
+#endif
+
+#ifdef CONFIG_STM32_UART5
+ /* UART5 clock enable */
+
+ regval |= RCC_APB1ENR_UART5EN;
+#endif
+
+#ifdef CONFIG_STM32_I2C1
+ /* I2C1 clock enable */
+
+ regval |= RCC_APB1ENR_I2C1EN;
+#endif
+
+#ifdef CONFIG_STM32_I2C2
+ /* I2C2 clock enable */
+
+ regval |= RCC_APB1ENR_I2C2EN;
+#endif
+
+#ifdef CONFIG_STM32_I2C3
+ /* I2C3 clock enable */
+
+ regval |= RCC_APB1ENR_I2C3EN;
+#endif
+
+#ifdef CONFIG_STM32_CAN1
+ /* CAN 1 clock enable */
+
+ regval |= RCC_APB1ENR_CAN1EN;
+#endif
+
+#ifdef CONFIG_STM32_CAN2
+ /* CAN2 clock enable. NOTE: CAN2 needs CAN1 clock as well. */
+
+ regval |= (RCC_APB1ENR_CAN1EN | RCC_APB1ENR_CAN2EN);
+#endif
+
+ /* Power interface clock enable. The PWR block is always enabled so that
+ * we can set the internal voltage regulator for maximum performance.
+ */
+
+ regval |= RCC_APB1ENR_PWREN;
+
+#if defined (CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2)
+ /* DAC interface clock enable */
+
+ regval |= RCC_APB1ENR_DACEN;
+#endif
+
+ putreg32(regval, STM32_RCC_APB1ENR); /* Enable peripherals */
+}
+
+/****************************************************************************
+ * Name: rcc_enableapb2
+ *
+ * Description:
+ * Enable selected APB2 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableapb2(void)
+{
+ uint32_t regval;
+
+ /* Set the appropriate bits in the APB2ENR register to enabled the
+ * selected APB2 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_APB2ENR);
+
+#ifdef CONFIG_STM32_TIM1
+ /* TIM1 clock enable */
+
+ regval |= RCC_APB2ENR_TIM1EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM8
+ /* TIM8 clock enable */
+
+ regval |= RCC_APB2ENR_TIM8EN;
+#endif
+
+#ifdef CONFIG_STM32_USART1
+ /* USART1 clock enable */
+
+ regval |= RCC_APB2ENR_USART1EN;
+#endif
+
+#ifdef CONFIG_STM32_USART6
+ /* USART6 clock enable */
+
+ regval |= RCC_APB2ENR_USART6EN;
+#endif
+
+#ifdef CONFIG_STM32_ADC1
+ /* ADC1 clock enable */
+
+ regval |= RCC_APB2ENR_ADC1EN;
+#endif
+
+#ifdef CONFIG_STM32_ADC2
+ /* ADC2 clock enable */
+
+ regval |= RCC_APB2ENR_ADC2EN;
+#endif
+
+#ifdef CONFIG_STM32_ADC3
+ /* ADC3 clock enable */
+
+ regval |= RCC_APB2ENR_ADC3EN;
+#endif
+
+#ifdef CONFIG_STM32_SDIO
+ /* SDIO clock enable */
+
+ regval |= RCC_APB2ENR_SDIOEN;
+#endif
+
+#ifdef CONFIG_STM32_SPI1
+ /* SPI1 clock enable */
+
+ regval |= RCC_APB2ENR_SPI1EN;
+#endif
+
+#ifdef CONFIG_STM32_SYSCFG
+ /* System configuration controller clock enable */
+
+ regval |= RCC_APB2ENR_SYSCFGEN;
+#endif
+
+#ifdef CONFIG_STM32_TIM9
+ /* TIM9 clock enable */
+
+ regval |= RCC_APB2ENR_TIM9EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM10
+ /* TIM10 clock enable */
+
+ regval |= RCC_APB2ENR_TIM10EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM11
+ /* TIM11 clock enable */
+
+ regval |= RCC_APB2ENR_TIM11EN;
+#endif
+
+ putreg32(regval, STM32_RCC_APB2ENR); /* Enable peripherals */
+}
+
+/****************************************************************************
+ * Name: stm32_stdclockconfig
+ *
+ * Description:
+ * Called to change to new clock based on settings in board.h
+ *
+ * NOTE: This logic would need to be extended if you need to select low-
+ * power clocking modes!
+ ****************************************************************************/
+
+#ifndef CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG
+static void stm32_stdclockconfig(void)
+{
+ uint32_t regval;
+ volatile int32_t timeout;
+
+ /* Enable External High-Speed Clock (HSE) */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval |= RCC_CR_HSEON; /* Enable HSE */
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Wait until the HSE is ready (or until a timeout elapsed) */
+
+ for (timeout = HSERDY_TIMEOUT; timeout > 0; timeout--)
+ {
+ /* Check if the HSERDY flag is the set in the CR */
+
+ if ((getreg32(STM32_RCC_CR) & RCC_CR_HSERDY) != 0)
+ {
+ /* If so, then break-out with timeout > 0 */
+
+ break;
+ }
+ }
+
+ /* Check for a timeout. If this timeout occurs, then we are hosed. We
+ * have no real back-up plan, although the following logic makes it look
+ * as though we do.
+ */
+
+ if (timeout > 0)
+ {
+ /* Select regulator voltage output Scale 1 mode to support system
+ * frequencies up to 168 MHz.
+ */
+
+ regval = getreg32(STM32_RCC_APB1ENR);
+ regval |= RCC_APB1ENR_PWREN;
+ putreg32(regval, STM32_RCC_APB1ENR);
+
+ regval = getreg32(STM32_PWR_CR);
+ regval |= PWR_CR_VOS;
+ putreg32(regval, STM32_PWR_CR);
+
+ /* Set the HCLK source/divider */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_HPRE_MASK;
+ regval |= STM32_RCC_CFGR_HPRE;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Set the PCLK2 divider */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_PPRE2_MASK;
+ regval |= STM32_RCC_CFGR_PPRE2;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Set the PCLK1 divider */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_PPRE1_MASK;
+ regval |= STM32_RCC_CFGR_PPRE1;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Set the PLL dividers and multiplers to configure the main PLL */
+
+ regval = (STM32_PLLCFG_PLLM | STM32_PLLCFG_PLLN |STM32_PLLCFG_PLLP |
+ RCC_PLLCFG_PLLSRC_HSE | STM32_PLLCFG_PPQ);
+ putreg32(regval, STM32_RCC_PLLCFG);
+
+ /* Enable the main PLL */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval |= RCC_CR_PLLON;
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Wait until the PLL is ready */
+
+ while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLRDY) == 0);
+
+ /* Enable FLASH prefetch, instruction cache, data cache, and 5 wait states */
+
+ regval = (FLASH_ACR_LATENCY_5 | FLASH_ACR_ICEN | FLASH_ACR_DCEN);
+ putreg32(regval, STM32_FLASH_ACR);
+
+ /* Select the main PLL as system clock source */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_SW_MASK;
+ regval |= RCC_CFGR_SW_PLL;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Wait until the PLL source is used as the system clock source */
+
+ while ((getreg32(STM32_RCC_CFGR) & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: rcc_enableperiphals
+ ****************************************************************************/
+
+static inline void rcc_enableperipherals(void)
+{
+ rcc_enableahb1();
+ rcc_enableahb2();
+ rcc_enableahb3();
+ rcc_enableapb1();
+ rcc_enableapb2();
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
diff --git a/nuttx/arch/arm/src/stm32/stm32f20xxx_rtc.c b/nuttx/arch/arm/src/stm32/stm32f20xxx_rtc.c
new file mode 100644
index 000000000..b98276498
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32f20xxx_rtc.c
@@ -0,0 +1,842 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32f20xxx_rtc.c
+ *
+ * Copyright (C) 2012 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 <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/rtc.h>
+
+#include <time.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+
+#include "stm32_rtc.h"
+
+#ifdef CONFIG_RTC
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* This RTC implementation supports only date/time RTC hardware */
+
+#ifndef CONFIG_RTC_DATETIME
+# error "CONFIG_RTC_DATETIME must be set to use this driver"
+#endif
+
+#ifdef CONFIG_RTC_HIRES
+# error "CONFIG_RTC_HIRES must NOT be set with this driver"
+#endif
+
+#ifndef CONFIG_STM32_PWR
+# error "CONFIG_STM32_PWR must selected to use this driver"
+#endif
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_DEBUG_RTC
+#endif
+
+/* Constants ************************************************************************/
+
+#define SYNCHRO_TIMEOUT (0x00020000)
+#define INITMODE_TIMEOUT (0x00010000)
+#define RTC_MAGIC (0xfacefeed)
+#define RTC_PREDIV_S (0xff)
+#define RTC_PREDIV_A (0x7f)
+
+/* Debug ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_RTC
+# define rtcdbg dbg
+# define rtcvdbg vdbg
+# define rtclldbg lldbg
+# define rtcllvdbg llvdbg
+#else
+# define rtcdbg(x...)
+# define rtcvdbg(x...)
+# define rtclldbg(x...)
+# define rtcllvdbg(x...)
+#endif
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Private Data
+ ************************************************************************************/
+
+/* Callback to use when the alarm expires */
+
+#ifdef CONFIG_RTC_ALARM
+static alarmcb_t g_alarmcb;
+#endif
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/* g_rtc_enabled is set true after the RTC has successfully initialized */
+
+volatile bool g_rtc_enabled = false;
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+/************************************************************************************
+ * Name: rtc_dumpregs
+ *
+ * Description:
+ * Disable RTC write protection
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_DEBUG_RTC
+static void rtc_dumpregs(FAR const char *msg)
+{
+ rtclldbg("%s:\n", msg);
+ rtclldbg(" TR: %08x\n", getreg32(STM32_RTC_TR));
+ rtclldbg(" DR: %08x\n", getreg32(STM32_RTC_DR));
+ rtclldbg(" CR: %08x\n", getreg32(STM32_RTC_CR));
+ rtclldbg(" ISR: %08x\n", getreg32(STM32_RTC_ISR));
+ rtclldbg(" PRER: %08x\n", getreg32(STM32_RTC_PRER));
+ rtclldbg(" WUTR: %08x\n", getreg32(STM32_RTC_WUTR));
+ rtclldbg(" CALIBR: %08x\n", getreg32(STM32_RTC_CALIBR));
+ rtclldbg(" ALRMAR: %08x\n", getreg32(STM32_RTC_ALRMAR));
+ rtclldbg(" ALRMBR: %08x\n", getreg32(STM32_RTC_ALRMBR));
+ rtclldbg(" SHIFTR: %08x\n", getreg32(STM32_RTC_SHIFTR));
+ rtclldbg(" TSTR: %08x\n", getreg32(STM32_RTC_TSTR));
+ rtclldbg(" TSDR: %08x\n", getreg32(STM32_RTC_TSDR));
+ rtclldbg(" TSSSR: %08x\n", getreg32(STM32_RTC_TSSSR));
+ rtclldbg(" CALR: %08x\n", getreg32(STM32_RTC_CALR));
+ rtclldbg(" TAFCR: %08x\n", getreg32(STM32_RTC_TAFCR));
+ rtclldbg("ALRMASSR: %08x\n", getreg32(STM32_RTC_ALRMASSR));
+ rtclldbg("ALRMBSSR: %08x\n", getreg32(STM32_RTC_ALRMBSSR));
+ rtclldbg(" BK0: %08x\n", getreg32(STM32_RTC_BK0R));
+}
+#else
+# define rtc_dumpregs(msg)
+#endif
+
+/************************************************************************************
+ * Name: rtc_dumptime
+ *
+ * Description:
+ * Disable RTC write protection
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_DEBUG_RTC
+static void rtc_dumptime(FAR struct tm *tp, FAR const char *msg)
+{
+ rtclldbg("%s:\n", msg);
+ rtclldbg(" tm_sec: %08x\n", tp->tm_sec);
+ rtclldbg(" tm_min: %08x\n", tp->tm_min);
+ rtclldbg(" tm_hour: %08x\n", tp->tm_hour);
+ rtclldbg(" tm_mday: %08x\n", tp->tm_mday);
+ rtclldbg(" tm_mon: %08x\n", tp->tm_mon);
+ rtclldbg(" tm_year: %08x\n", tp->tm_year);
+}
+#else
+# define rtc_dumptime(tp, msg)
+#endif
+
+/************************************************************************************
+ * Name: rtc_wprunlock
+ *
+ * Description:
+ * Disable RTC write protection
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static void rtc_wprunlock(void)
+{
+ /* The following steps are required to unlock the write protection on all the
+ * RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR).
+ *
+ * 1. Write 0xCA into the RTC_WPR register.
+ * 2. Write 0x53 into the RTC_WPR register.
+ *
+ * Writing a wrong key reactivates the write protection.
+ */
+
+ putreg32(0xca, STM32_RTC_WPR);
+ putreg32(0x53, STM32_RTC_WPR);
+}
+
+/************************************************************************************
+ * Name: rtc_wprunlock
+ *
+ * Description:
+ * Enable RTC write protection
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static inline void rtc_wprlock(void)
+{
+ /* Writing any wrong key reactivates the write protection. */
+
+ putreg32(0xff, STM32_RTC_WPR);
+}
+
+/************************************************************************************
+ * Name: rtc_synchwait
+ *
+ * Description:
+ * Waits until the RTC Time and Date registers (RTC_TR and RTC_DR) are
+ * synchronized with RTC APB clock.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static int rtc_synchwait(void)
+{
+ volatile uint32_t timeout;
+ uint32_t regval;
+ int ret;
+
+ /* Disable the write protection for RTC registers */
+
+ rtc_wprunlock();
+
+ /* Clear Registers synchronization flag (RSF) */
+
+ regval = getreg32(STM32_RTC_ISR);
+ regval &= ~RTC_ISR_RSF;
+ putreg32(regval, STM32_RTC_ISR);
+
+ /* Now wait the registers to become synchronised */
+
+ ret = -ETIMEDOUT;
+ for (timeout = 0; timeout < SYNCHRO_TIMEOUT; timeout++)
+ {
+ regval = getreg32(STM32_RTC_ISR);
+ if ((regval & RTC_ISR_RSF) != 0)
+ {
+ /* Synchronized */
+
+ ret = OK;
+ break;
+ }
+ }
+
+ /* Re-enable the write protection for RTC registers */
+
+ rtc_wprlock();
+ return ret;
+}
+
+/************************************************************************************
+ * Name: rtc_enterinit
+ *
+ * Description:
+ * Enter RTC initialization mode.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static int rtc_enterinit(void)
+{
+ volatile uint32_t timeout;
+ uint32_t regval;
+ int ret;
+
+ /* Check if the Initialization mode is already set */
+
+ regval = getreg32(STM32_RTC_ISR);
+
+ ret = OK;
+ if ((regval & RTC_ISR_INITF) == 0)
+ {
+ /* Set the Initialization mode */
+
+ putreg32(RTC_ISR_INIT, STM32_RTC_ISR);
+
+ /* Wait until the RTC is in the INIT state (or a timeout occurs) */
+
+ ret = -ETIMEDOUT;
+ for (timeout = 0; timeout < INITMODE_TIMEOUT; timeout++)
+ {
+ regval = getreg32(STM32_RTC_ISR);
+ if ((regval & RTC_ISR_INITF) != 0)
+ {
+ ret = OK;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/************************************************************************************
+ * Name: rtc_exitinit
+ *
+ * Description:
+ * Exit RTC initialization mode.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static void rtc_exitinit(void)
+{
+ uint32_t regval;
+
+ regval = getreg32(STM32_RTC_ISR);
+ regval &= ~(RTC_ISR_INIT);
+ putreg32(regval, STM32_RTC_ISR);
+}
+
+/************************************************************************************
+ * Name: rtc_bin2bcd
+ *
+ * Description:
+ * Converts a 2 digit binary to BCD format
+ *
+ * Input Parameters:
+ * value - The byte to be converted.
+ *
+ * Returned Value:
+ * The value in BCD representation
+ *
+ ************************************************************************************/
+
+static uint32_t rtc_bin2bcd(int value)
+{
+ uint32_t msbcd = 0;
+
+ while (value >= 10)
+ {
+ msbcd++;
+ value -= 10;
+ }
+
+ return (msbcd << 4) | value;
+}
+
+/************************************************************************************
+ * Name: rtc_bin2bcd
+ *
+ * Description:
+ * Convert from 2 digit BCD to binary.
+ *
+ * Input Parameters:
+ * value - The BCD value to be converted.
+ *
+ * Returned Value:
+ * The value in binary representation
+ *
+ ************************************************************************************/
+
+static int rtc_bcd2bin(uint32_t value)
+{
+ uint32_t tens = (value >> 4) * 10;
+ return (int)(tens + (value & 0x0f));
+}
+
+/************************************************************************************
+ * Name: rtc_setup
+ *
+ * Description:
+ * Performs first time configuration of the RTC. A special value written into
+ * back-up register 0 will prevent this function from being called on sub-sequent
+ * resets or power up.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static int rtc_setup(void)
+{
+ uint32_t regval;
+ int ret;
+
+ /* Enable the External Low-Speed (LSE) Oscillator setup the LSE as the RTC clock\
+ * source, and enable the RTC.
+ */
+
+ stm32_rcc_enablelse();
+
+ /* Wait for the RTC Time and Date registers to be synchronized with RTC APB
+ * clock.
+ */
+
+ ret = rtc_synchwait();
+ if (ret == OK)
+ {
+ /* Disable the write protection for RTC registers */
+
+ rtc_wprunlock();
+
+ /* Set Initialization mode */
+
+ ret = rtc_enterinit();
+ if (ret == OK)
+ {
+ /* Set the 24 hour format by clearing the FMT bit in the RTC
+ * control register
+ */
+
+ regval = getreg32(STM32_RTC_CR);
+ regval &= ~RTC_CR_FMT;
+ putreg32(regval, STM32_RTC_CR);
+
+ /* Configure RTC pre-scaler to the required, default values for
+ * use with the 32.768 KHz LSE clock:
+ */
+
+ putreg32(((uint32_t)0xff << RTC_PRER_PREDIV_S_SHIFT) |
+ ((uint32_t)0x7f << RTC_PRER_PREDIV_A_SHIFT),
+ STM32_RTC_PRER);
+
+ /* Exit RTC initialization mode */
+
+ rtc_exitinit();
+ }
+
+ /* Re-enable the write protection for RTC registers */
+
+ rtc_wprlock();
+ }
+ return ret;
+}
+
+/************************************************************************************
+ * Name: rtc_resume
+ *
+ * Description:
+ * Called when the RTC was already initialized on a previous power cycle. This
+ * just brings the RTC back into full operation.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static int rtc_resume(void)
+{
+#ifdef CONFIG_RTC_ALARM
+ uint32_t regval;
+#endif
+ int ret;
+
+ /* Wait for the RTC Time and Date registers to be syncrhonized with RTC APB
+ * clock.
+ */
+
+ ret = rtc_synchwait();
+
+ /* Clear the RTC alarm flags */
+
+#ifdef CONFIG_RTC_ALARM
+ regval = getreg32(STM32_RTC_ISR);
+ regval &= ~(RTC_ISR_ALRAF|RTC_ISR_ALRBF);
+ putreg32(regval, STM32_RTC_ISR);
+
+ /* Clear the EXTI Line 17 Pending bit (Connected internally to RTC Alarm) */
+
+ putreg32((1 << 17), STM32_EXTI_PR);
+#endif
+ return ret;
+}
+
+/************************************************************************************
+ * Name: rtc_interrupt
+ *
+ * Description:
+ * RTC interrupt service routine
+ *
+ * Input Parameters:
+ * irq - The IRQ number that generated the interrupt
+ * context - Architecture specific register save information.
+ *
+ * Returned Value:
+ * Zero (OK) on success; A negated errno value on failure.
+ *
+ ************************************************************************************/
+
+#if CONFIG_RTC_ALARM
+static int rtc_interrupt(int irq, void *context)
+{
+#warning "Missing logic"
+ return OK;
+}
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_rtcinitialize
+ *
+ * Description:
+ * Initialize the hardware RTC per the selected configuration. This function is
+ * called once during the OS initialization sequence
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtcinitialize(void)
+{
+ uint32_t regval;
+ int ret;
+
+ rtc_dumpregs("On reset");
+
+ /* Clocking for the PWR block must be provided. However, this is done
+ * unconditionally in stm32f40xxx_rcc.c on power up. This done unconditionally
+ * because the PWR block is also needed to set the internal voltage regulator for
+ * maximum performance.
+ */
+
+ /* Enable access to the backup domain (RTC registers, RTC backup data registers
+ * and backup SRAM).
+ */
+
+ stm32_pwr_enablebkp();
+
+ /* Check if the one-time initialization of the RTC has already been performed.
+ * We can determine this by checking if the magic number has been writing to
+ * to back-up date register DR0.
+ */
+
+ regval = getreg32(STM32_RTC_BK0R);
+ if (regval != RTC_MAGIC)
+ {
+ /* Perform the one-time setup of the LSE clocking to the RTC */
+
+ ret = rtc_setup();
+
+ /* Remember that the RTC is initialized */
+
+ putreg32(RTC_MAGIC, STM32_RTC_BK0R);
+ }
+ else
+ {
+ /* RTC already set-up, just resume normal operation */
+
+ ret = rtc_resume();
+ }
+
+ /* Configure RTC interrupt to catch alarm interrupts. All RTC interrupts are
+ * connected to the EXTI controller. To enable the RTC Alarm interrupt, the
+ * following sequence is required:
+ *
+ * 1. Configure and enable the EXTI Line 17 in interrupt mode and select the
+ * rising edge sensitivity.
+ * 2. Configure and enable the RTC_Alarm IRQ channel in the NVIC.
+ * 3. Configure the RTC to generate RTC alarms (Alarm A or Alarm B).
+ */
+
+#ifdef CONFIG_RTC_ALARM
+# warning "Missing EXTI setup logic"
+
+ /* Then attach the ALARM interrupt handler */
+
+ irq_attach(STM32_IRQ_RTC, rtc_interrupt);
+ up_enable_irq(STM32_IRQ_RTC);
+#endif
+
+ g_rtc_enabled = true;
+ rtc_dumpregs("After Initialzation");
+ return OK;
+}
+
+/************************************************************************************
+ * Name: up_rtc_getdatetime
+ *
+ * Description:
+ * Get the current date and time from the date/time RTC. This interface
+ * is only supported by the date/time RTC hardware implementation.
+ * It is used to replace the system timer. It is only used by the RTOS during
+ * intialization to set up the system time when CONFIG_RTC and CONFIG_RTC_DATETIME
+ * are selected (and CONFIG_RTC_HIRES is not).
+ *
+ * NOTE: Some date/time RTC hardware is capability of sub-second accuracy. That
+ * sub-second accuracy is lost in this interface. However, since the system time
+ * is reinitialized on each power-up/reset, there will be no timing inaccuracy in
+ * the long run.
+ *
+ * Input Parameters:
+ * tp - The location to return the high resolution time value.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtc_getdatetime(FAR struct tm *tp)
+{
+ uint32_t dr;
+ uint32_t tr;
+ uint32_t tmp;
+
+ /* Sample the data time registers. There is a race condition here... If we sample
+ * the time just before midnight on December 31, the date could be wrong because
+ * the day rolled over while were sampling.
+ */
+
+ do
+ {
+ dr = getreg32(STM32_RTC_DR);
+ tr = getreg32(STM32_RTC_TR);
+ tmp = getreg32(STM32_RTC_DR);
+ }
+ while (tmp != dr);
+
+ rtc_dumpregs("Reading Time");
+
+ /* Convert the RTC time to fields in struct tm format. All of the STM32
+ * All of the ranges of values correspond between struct tm and the time
+ * register.
+ */
+
+ tmp = (tr & (RTC_TR_SU_MASK|RTC_TR_ST_MASK)) >> RTC_TR_SU_SHIFT;
+ tp->tm_sec = rtc_bcd2bin(tmp);
+
+ tmp = (tr & (RTC_TR_MNU_MASK|RTC_TR_MNT_MASK)) >> RTC_TR_MNU_SHIFT;
+ tp->tm_min = rtc_bcd2bin(tmp);
+
+ tmp = (tr & (RTC_TR_HU_MASK|RTC_TR_HT_MASK)) >> RTC_TR_HU_SHIFT;
+ tp->tm_hour = rtc_bcd2bin(tmp);
+
+ /* Now convert the RTC date to fields in struct tm format:
+ * Days: 1-31 match in both cases.
+ * Month: STM32 is 1-12, struct tm is 0-11.
+ * Years: STM32 is 00-99, struct tm is years since 1900.
+ *
+ * Issue: I am not sure what the STM32 years mean. Are these the
+ * years 2000-2099? I'll assume so.
+ */
+
+ tmp = (dr & (RTC_DR_DU_MASK|RTC_DR_DT_MASK)) >> RTC_DR_DU_SHIFT;
+ tp->tm_mday = rtc_bcd2bin(tmp);
+
+ tmp = (dr & (RTC_DR_MU_MASK|RTC_DR_MT)) >> RTC_DR_MU_SHIFT;
+ tp->tm_mon = rtc_bcd2bin(tmp) - 1;
+
+ tmp = (dr & (RTC_DR_YU_MASK|RTC_DR_YT_MASK)) >> RTC_DR_YU_SHIFT;
+ tp->tm_year = rtc_bcd2bin(tmp) + 100;
+
+ rtc_dumptime(tp, "Returning");
+ return OK;
+}
+
+/************************************************************************************
+ * Name: up_rtc_settime
+ *
+ * Description:
+ * Set the RTC to the provided time. All RTC implementations must be able to
+ * set their time based on a standard timespec.
+ *
+ * Input Parameters:
+ * tp - the time to use
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtc_settime(FAR const struct timespec *tp)
+{
+ FAR struct tm newtime;
+ uint32_t tr;
+ uint32_t dr;
+ int ret;
+
+ /* Break out the time values (not that the time is set only to units of seconds) */
+
+ (void)gmtime_r(&tp->tv_sec, &newtime);
+ rtc_dumptime(&newtime, "Setting time");
+
+ /* Then write the broken out values to the RTC */
+
+ /* Convert the struct tm format to RTC time register fields. All of the STM32
+ * All of the ranges of values correspond between struct tm and the time
+ * register.
+ */
+
+ tr = (rtc_bin2bcd(newtime.tm_sec) << RTC_TR_SU_SHIFT) |
+ (rtc_bin2bcd(newtime.tm_min) << RTC_TR_MNU_SHIFT) |
+ (rtc_bin2bcd(newtime.tm_hour) << RTC_TR_HU_SHIFT);
+ tr &= ~RTC_TR_RESERVED_BITS;
+
+ /* Now convert the fields in struct tm format to the RTC date register fields:
+ * Days: 1-31 match in both cases.
+ * Month: STM32 is 1-12, struct tm is 0-11.
+ * Years: STM32 is 00-99, struct tm is years since 1900.
+ *
+ * Issue: I am not sure what the STM32 years mean. Are these the
+ * years 2000-2099? I'll assume so.
+ */
+
+ dr = (rtc_bin2bcd(newtime.tm_mday) << RTC_DR_DU_SHIFT) |
+ ((rtc_bin2bcd(newtime.tm_mon + 1)) << RTC_DR_MU_SHIFT) |
+ ((rtc_bin2bcd(newtime.tm_year - 100)) << RTC_DR_YU_SHIFT);
+ dr &= ~RTC_DR_RESERVED_BITS;
+
+ /* Disable the write protection for RTC registers */
+
+ rtc_wprunlock();
+
+ /* Set Initialization mode */
+
+ ret = rtc_enterinit();
+ if (ret == OK)
+ {
+ /* Set the RTC TR and DR registers */
+
+ putreg32(tr, STM32_RTC_TR);
+ putreg32(dr, STM32_RTC_DR);
+
+ /* Exit Initialization mode and wait for the RTC Time and Date
+ * registers to be synchronized with RTC APB clock.
+ */
+
+ rtc_exitinit();
+ ret = rtc_synchwait();
+ }
+
+ /* Re-enable the write protection for RTC registers */
+
+ rtc_wprlock();
+ rtc_dumpregs("New time setting");
+ return ret;
+}
+
+/************************************************************************************
+ * Name: up_rtc_setalarm
+ *
+ * Description:
+ * Set up an alarm. Up to two alarms can be supported (ALARM A and ALARM B).
+ *
+ * Input Parameters:
+ * tp - the time to set the alarm
+ * callback - the function to call when the alarm expires.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback);
+{
+ irqstate_t flags;
+ int ret = -EBUSY;
+
+ /* Is there already something waiting on the ALARM? */
+
+ if (g_alarmcb == NULL)
+ {
+ /* No.. Save the callback function pointer */
+
+ g_alarmcb = callback;
+
+ /* Break out the time values */
+#warning "Missing logic"
+
+ /* The set the alarm */
+#warning "Missing logic"
+
+ ret = OK;
+ }
+ return ret;
+}
+#endif
+
+#endif /* CONFIG_RTC */
+
diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c
new file mode 100644
index 000000000..c3555d714
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c
@@ -0,0 +1,903 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32f40xxx_dma.c
+ *
+ * Copyright (C) 2011-2012 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 <stdbool.h>
+#include <semaphore.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/irq.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+#include "os_internal.h"
+#include "chip.h"
+#include "stm32_dma.h"
+#include "stm32_internal.h"
+
+/* This file supports only the STM32 F4 family (an probably the F2 family
+ * as well?)
+ */
+
+#if defined(CONFIG_STM32_STM32F40XX)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DMA1_NSTREAMS 8
+#if STM32_NDMA > 1
+# define DMA2_NSTREAMS 8
+# define DMA_NSTREAMS (DMA1_NSTREAMS+DMA2_NSTREAMS)
+#else
+# define DMA_NSTREAMS DMA1_NSTREAMS
+#endif
+
+#ifndef CONFIG_DMA_PRI
+# define CONFIG_DMA_PRI NVIC_SYSH_PRIORITY_DEFAULT
+#endif
+
+/* Convert the DMA stream base address to the DMA register block address */
+
+#define DMA_BASE(ch) (ch & 0xfffffc00)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure descibes one DMA channel */
+
+struct stm32_dma_s
+{
+ uint8_t stream; /* DMA stream number (0-7) */
+ uint8_t irq; /* DMA stream IRQ number */
+ uint8_t shift; /* ISR/IFCR bit shift value */
+ uint8_t channel; /* DMA channel number (0-7) */
+ bool nonstop; /* Stream is configured in a non-stopping mode. */
+ sem_t sem; /* Used to wait for DMA channel to become available */
+ uint32_t base; /* DMA register channel base address */
+ dma_callback_t callback; /* Callback invoked when the DMA completes */
+ void *arg; /* Argument passed to callback function */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This array describes the state of each DMA */
+
+static struct stm32_dma_s g_dma[DMA_NSTREAMS] =
+{
+ {
+ .stream = 0,
+ .irq = STM32_IRQ_DMA1S0,
+ .shift = DMA_INT_STREAM0_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(0),
+ },
+ {
+ .stream = 1,
+ .irq = STM32_IRQ_DMA1S1,
+ .shift = DMA_INT_STREAM1_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(1),
+ },
+ {
+ .stream = 2,
+ .irq = STM32_IRQ_DMA1S2,
+ .shift = DMA_INT_STREAM2_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(2),
+ },
+ {
+ .stream = 3,
+ .irq = STM32_IRQ_DMA1S3,
+ .shift = DMA_INT_STREAM3_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(4),
+ },
+ {
+ .stream = 4,
+ .irq = STM32_IRQ_DMA1S4,
+ .shift = DMA_INT_STREAM4_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(4),
+ },
+ {
+ .stream = 5,
+ .irq = STM32_IRQ_DMA1S5,
+ .shift = DMA_INT_STREAM5_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(5),
+ },
+ {
+ .stream = 6,
+ .irq = STM32_IRQ_DMA1S6,
+ .shift = DMA_INT_STREAM6_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(6),
+ },
+ {
+ .stream = 7,
+ .irq = STM32_IRQ_DMA1S7,
+ .shift = DMA_INT_STREAM7_SHIFT,
+ .base = STM32_DMA1_BASE + STM32_DMA_OFFSET(7),
+ },
+#if STM32_NDMA > 1
+ {
+ .stream = 0,
+ .irq = STM32_IRQ_DMA2S0,
+ .shift = DMA_INT_STREAM0_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(0),
+ },
+ {
+ .stream = 1,
+ .irq = STM32_IRQ_DMA2S1,
+ .shift = DMA_INT_STREAM1_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(1),
+ },
+ {
+ .stream = 2,
+ .irq = STM32_IRQ_DMA2S2,
+ .shift = DMA_INT_STREAM2_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(2),
+ },
+ {
+ .stream = 3,
+ .irq = STM32_IRQ_DMA2S3,
+ .shift = DMA_INT_STREAM3_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(3),
+ },
+ {
+ .stream = 4,
+ .irq = STM32_IRQ_DMA2S4,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(4),
+ },
+ {
+ .stream = 5,
+ .irq = STM32_IRQ_DMA2S5,
+ .shift = DMA_INT_STREAM5_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(5),
+ },
+ {
+ .stream = 6,
+ .irq = STM32_IRQ_DMA2S6,
+ .shift = DMA_INT_STREAM6_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(6),
+ },
+ {
+ .stream = 7,
+ .irq = STM32_IRQ_DMA2S7,
+ .shift = DMA_INT_STREAM7_SHIFT,
+ .base = STM32_DMA2_BASE + STM32_DMA_OFFSET(7),
+ },
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * DMA register access functions
+ ****************************************************************************/
+
+/* Get non-channel register from DMA1 or DMA2 */
+
+static inline uint32_t dmabase_getreg(struct stm32_dma_s *dmast, uint32_t offset)
+{
+ return getreg32(DMA_BASE(dmast->base) + offset);
+}
+
+/* Write to non-channel register in DMA1 or DMA2 */
+
+static inline void dmabase_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value)
+{
+ putreg32(value, DMA_BASE(dmast->base) + offset);
+}
+
+/* Get channel register from DMA1 or DMA2 */
+
+static inline uint32_t dmast_getreg(struct stm32_dma_s *dmast, uint32_t offset)
+{
+ return getreg32(dmast->base + offset);
+}
+
+/* Write to channel register in DMA1 or DMA2 */
+
+static inline void dmast_putreg(struct stm32_dma_s *dmast, uint32_t offset, uint32_t value)
+{
+ putreg32(value, dmast->base + offset);
+}
+
+/************************************************************************************
+ * Name: stm32_dmatake() and stm32_dmagive()
+ *
+ * Description:
+ * Used to get exclusive access to a DMA channel.
+ *
+ ************************************************************************************/
+
+static void stm32_dmatake(FAR struct stm32_dma_s *dmast)
+{
+ /* Take the semaphore (perhaps waiting) */
+
+ while (sem_wait(&dmast->sem) != 0)
+ {
+ /* The only case that an error should occur here is if the wait was awakened
+ * by a signal.
+ */
+
+ ASSERT(errno == EINTR);
+ }
+}
+
+static inline void stm32_dmagive(FAR struct stm32_dma_s *dmast)
+{
+ (void)sem_post(&dmast->sem);
+}
+
+/************************************************************************************
+ * Name: stm32_dmastream
+ *
+ * Description:
+ * Get the g_dma table entry associated with a DMA controller and a stream number
+ *
+ ************************************************************************************/
+
+static inline FAR struct stm32_dma_s *stm32_dmastream(unsigned int stream,
+ unsigned int controller)
+{
+ int index;
+
+ DEBUGASSERT(stream < DMA_NSTREAMS && controller < STM32_NDMA);
+
+ /* Convert the controller + stream based on the fact that there are 8 streams
+ * per controller.
+ */
+
+#if STM32_NDMA > 1
+ index = controller << 3 | stream;
+#else
+ index = stream;
+#endif
+
+ /* Then return the stream structure associated with the stream index */
+
+ return &g_dma[index];
+}
+
+/************************************************************************************
+ * Name: stm32_dmamap
+ *
+ * Description:
+ * Get the g_dma table entry associated with a bit-encoded DMA selection
+ *
+ ************************************************************************************/
+
+static inline FAR struct stm32_dma_s *stm32_dmamap(unsigned long dmamap)
+{
+ /* Extract the DMA controller number from the bit encoded value */
+
+ unsigned int controller = STM32_DMA_CONTROLLER(dmamap);
+
+ /* Extact the stream number from the bit encoded value */
+
+ unsigned int stream = STM32_DMA_STREAM(dmamap);
+
+ /* Return the table entry associated with the controller + stream */
+
+ return stm32_dmastream(stream, controller);
+}
+
+/************************************************************************************
+ * Name: stm32_dmastreamdisable
+ *
+ * Description:
+ * Disable the DMA stream
+ *
+ ************************************************************************************/
+
+static void stm32_dmastreamdisable(struct stm32_dma_s *dmast)
+{
+ uint32_t regoffset;
+ uint32_t regval;
+
+ /* Disable all interrupts at the DMA controller */
+
+ regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ regval &= ~DMA_SCR_ALLINTS;
+
+ /* Disable the DMA stream */
+
+ regval &= ~DMA_SCR_EN;
+ dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
+
+ /* Clear pending stream interrupts by setting bits in the upper or lower IFCR
+ * register
+ */
+
+ if (dmast->stream < 4)
+ {
+ regoffset = STM32_DMA_LIFCR_OFFSET;
+ }
+ else
+ {
+ regoffset = STM32_DMA_HIFCR_OFFSET;
+ }
+
+ dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift));
+}
+
+/************************************************************************************
+ * Name: stm32_dmainterrupt
+ *
+ * Description:
+ * DMA interrupt handler
+ *
+ ************************************************************************************/
+
+static int stm32_dmainterrupt(int irq, void *context)
+{
+ struct stm32_dma_s *dmast;
+ uint32_t status;
+ uint32_t regoffset = 0;
+ unsigned int stream = 0;
+ unsigned int controller = 0;
+
+ /* Get the stream and the controller that generated the interrupt */
+
+ if (irq >= STM32_IRQ_DMA1S0 && irq <= STM32_IRQ_DMA1S6)
+ {
+ stream = irq - STM32_IRQ_DMA1S0;
+ controller = DMA1;
+ }
+ else if (irq == STM32_IRQ_DMA1S7)
+ {
+ stream = 7;
+ controller = DMA1;
+ }
+ else
+#if STM32_NDMA > 1
+ if (irq >= STM32_IRQ_DMA2S0 && irq <= STM32_IRQ_DMA2S4)
+ {
+ stream = irq - STM32_IRQ_DMA2S0;
+ controller = DMA2;
+ }
+ else if (irq >= STM32_IRQ_DMA2S5 && irq <= STM32_IRQ_DMA2S7)
+ {
+ stream = irq - STM32_IRQ_DMA2S5 + 5;
+ controller = DMA2;
+ }
+ else
+#endif
+ {
+ PANIC(OSERR_INTERNAL);
+ }
+
+ /* Get the stream structure from the stream and controller numbers */
+
+ dmast = stm32_dmastream(stream, controller);
+
+ /* Select the interrupt status register (either the LISR or HISR)
+ * based on the stream number that caused the interrupt.
+ */
+
+ if (stream < 4)
+ {
+ regoffset = STM32_DMA_LISR_OFFSET;
+ }
+ else
+ {
+ regoffset = STM32_DMA_HISR_OFFSET;
+ }
+
+ /* Get the interrupt status for this stream */
+
+ status = (dmabase_getreg(dmast, regoffset) >> dmast->shift) & DMA_STREAM_MASK;
+
+ /* Clear fetched stream interrupts by setting bits in the upper or lower IFCR
+ * register
+ */
+
+ if (stream < 4)
+ {
+ regoffset = STM32_DMA_LIFCR_OFFSET;
+ }
+ else
+ {
+ regoffset = STM32_DMA_HIFCR_OFFSET;
+ }
+
+ dmabase_putreg(dmast, regoffset, (status << dmast->shift));
+
+ /* Invoke the callback */
+
+ if (dmast->callback)
+ {
+ dmast->callback(dmast, status, dmast->arg);
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_dmainitialize
+ *
+ * Description:
+ * Initialize the DMA subsystem
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void weak_function up_dmainitialize(void)
+{
+ struct stm32_dma_s *dmast;
+ int stream;
+
+ /* Initialize each DMA stream */
+
+ for (stream = 0; stream < DMA_NSTREAMS; stream++)
+ {
+ dmast = &g_dma[stream];
+ sem_init(&dmast->sem, 0, 1);
+
+ /* Attach DMA interrupt vectors */
+
+ (void)irq_attach(dmast->irq, stm32_dmainterrupt);
+
+ /* Disable the DMA stream */
+
+ stm32_dmastreamdisable(dmast);
+
+ /* Enable the IRQ at the NVIC (still disabled at the DMA controller) */
+
+ up_enable_irq(dmast->irq);
+
+ /* Set the interrrupt priority */
+
+ up_prioritize_irq(dmast->irq, CONFIG_DMA_PRI);
+ }
+}
+
+/****************************************************************************
+ * Name: stm32_dmachannel
+ *
+ * Description:
+ * Allocate a DMA channel. This function gives the caller mutually
+ * exclusive access to the DMA channel specified by the 'dmamap' argument.
+ * DMA channels are shared on the STM32: Devices sharing the same DMA
+ * channel cannot do DMA concurrently! See the DMACHAN_* definitions in
+ * stm32_dma.h.
+ *
+ * If the DMA channel is not available, then stm32_dmachannel() will wait
+ * until the holder of the channel relinquishes the channel by calling
+ * stm32_dmafree(). WARNING: If you have two devices sharing a DMA
+ * channel and the code never releases the channel, the stm32_dmachannel
+ * call for the other will hang forever in this function! Don't let your
+ * design do that!
+ *
+ * Hmm.. I suppose this interface could be extended to make a non-blocking
+ * version. Feel free to do that if that is what you need.
+ *
+ * Input parameter:
+ * dmamap - Identifies the stream/channel resource. For the STM32 F4, this
+ * is a bit-encoded value as provided by the the DMAMAP_* definitions
+ * in chip/stm32f40xxx_dma.h
+ *
+ * Returned Value:
+ * Provided that 'dmamap' is valid, this function ALWAYS returns a non-NULL,
+ * void* DMA channel handle. (If 'dmamap' is invalid, the function will
+ * assert if debug is enabled or do something ignorant otherwise).
+ *
+ * Assumptions:
+ * - The caller does not hold he DMA channel.
+ * - The caller can wait for the DMA channel to be freed if it is no
+ * available.
+ *
+ ****************************************************************************/
+
+DMA_HANDLE stm32_dmachannel(unsigned int dmamap)
+{
+ FAR struct stm32_dma_s *dmast;
+
+ /* Get the stream index from the bit-encoded channel value */
+
+ dmast = stm32_dmamap(dmamap);
+ DEBUGASSERT(dmast != NULL);
+
+ /* Get exclusive access to the DMA channel -- OR wait until the channel
+ * is available if it is currently being used by another driver
+ */
+
+ stm32_dmatake(dmast);
+
+ /* The caller now has exclusive use of the DMA channel. Assign the
+ * channel to the stream and return an opaque reference to the stream
+ * structure.
+ */
+
+ dmast->channel = STM32_DMA_CHANNEL(dmamap);
+ return (DMA_HANDLE)dmast;
+}
+
+/****************************************************************************
+ * Name: stm32_dmafree
+ *
+ * Description:
+ * Release a DMA channel. If another thread is waiting for this DMA channel
+ * in a call to stm32_dmachannel, then this function will re-assign the
+ * DMA channel to that thread and wake it up. NOTE: The 'handle' used
+ * in this argument must NEVER be used again until stm32_dmachannel() is
+ * called again to re-gain access to the channel.
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * - The caller holds the DMA channel.
+ * - There is no DMA in progress
+ *
+ ****************************************************************************/
+
+void stm32_dmafree(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+
+ DEBUGASSERT(handle != NULL);
+
+ /* Release the channel */
+
+ stm32_dmagive(dmast);
+}
+
+/****************************************************************************
+ * Name: stm32_dmasetup
+ *
+ * Description:
+ * Configure DMA before using
+ *
+ ****************************************************************************/
+
+void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
+ size_t ntransfers, uint32_t scr)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ uint32_t regoffset;
+ uint32_t regval;
+
+ dmadbg("paddr: %08x maddr: %08x ntransfers: %d scr: %08x\n",
+ paddr, maddr, ntransfers, scr);
+
+ /* "If the stream is enabled, disable it by resetting the EN bit in the
+ * DMA_SxCR register, then read this bit in order to confirm that there is no
+ * ongoing stream operation. Writing this bit to 0 is not immediately
+ * effective since it is actually written to 0 once all the current transfers
+ * have finished. When the EN bit is read as 0, this means that the stream is
+ * ready to be configured. It is therefore necessary to wait for the EN bit
+ * to be cleared before starting any stream configuration. ..."
+ */
+
+ while ((dmast_getreg(dmast, STM32_DMA_SCR_OFFSET) & DMA_SCR_EN) != 0);
+
+ /* "... All the stream dedicated bits set in the status register (DMA_LISR
+ * and DMA_HISR) from the previous data block DMA transfer should be cleared
+ * before the stream can be re-enabled."
+ *
+ * Clear pending stream interrupts by setting bits in the upper or lower IFCR
+ * register
+ */
+
+ if (dmast->stream < 4)
+ {
+ regoffset = STM32_DMA_LIFCR_OFFSET;
+ }
+ else
+ {
+ regoffset = STM32_DMA_HIFCR_OFFSET;
+ }
+
+ dmabase_putreg(dmast, regoffset, (DMA_STREAM_MASK << dmast->shift));
+
+ /* "Set the peripheral register address in the DMA_SPARx register. The data
+ * will be moved from/to this address to/from the memory after the
+ * peripheral event.
+ */
+
+ dmast_putreg(dmast, STM32_DMA_SPAR_OFFSET, paddr);
+
+ /* "Set the memory address in the DMA_SM0ARx ... register. The data will be
+ * written to or read from this memory after the peripheral event."
+ *
+ * Note that in double-buffered mode it is explicitly assumed that the second
+ * buffer immediately follows the first.
+ */
+
+ dmast_putreg(dmast, STM32_DMA_SM0AR_OFFSET, maddr);
+ if (scr & DMA_SCR_DBM)
+ {
+ dmast_putreg(dmast, STM32_DMA_SM1AR_OFFSET, maddr + ntransfers);
+ }
+
+ /* "Configure the total number of data items to be transferred in the
+ * DMA_SNDTRx register. After each peripheral event, this value will be
+ * decremented."
+ *
+ * "When the peripheral flow controller is used for a given stream, the value
+ * written into the DMA_SxNDTR has no effect on the DMA transfer. Actually,
+ * whatever the value written, it will be forced by hardware to 0xFFFF as soon
+ * as the stream is enabled..."
+ */
+
+ dmast_putreg(dmast, STM32_DMA_SNDTR_OFFSET, ntransfers);
+
+ /* "Select the DMA channel (request) using CHSEL[2:0] in the DMA_SxCR register."
+ *
+ * "Configure the stream priority using the PL[1:0] bits in the DMA_SCRx"
+ * register."
+ */
+
+ regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ regval &= ~(DMA_SCR_PL_MASK|DMA_SCR_CHSEL_MASK);
+ regval |= scr & DMA_SCR_PL_MASK;
+ regval |= (uint32_t)dmast->channel << DMA_SCR_CHSEL_SHIFT;
+ dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
+
+ /* "Configure the FIFO usage (enable or disable, threshold in transmission and
+ * reception)"
+ *
+ * "Caution is required when choosing the FIFO threshold (bits FTH[1:0] of the
+ * DMA_SxFCR register) and the size of the memory burst (MBURST[1:0] of the
+ * DMA_SxCR register): The content pointed by the FIFO threshold must exactly
+ * match to an integer number of memory burst transfers. If this is not in the
+ * case, a FIFO error (flag FEIFx of the DMA_HISR or DMA_LISR register) will be
+ * generated when the stream is enabled, then the stream will be automatically
+ * disabled."
+ *
+ * The FIFO is disabled in circular mode when transferring data from a
+ * peripheral to memory, as in this case it is usually desirable to know that
+ * every byte from the peripheral is transferred immediately to memory. It is
+ * not practical to flush the DMA FIFO, as this requires disabling the channel
+ * which triggers the transfer-complete interrupt.
+ *
+ * NOTE: The FEIFx error interrupt is not enabled because the FEIFx seems to
+ * be reported spuriously causing good transfers to be marked as failures.
+ */
+
+ regval = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET);
+ regval &= ~(DMA_SFCR_FTH_MASK | DMA_SFCR_FS_MASK | DMA_SFCR_FEIE);
+ if (!((scr & (DMA_SCR_CIRC | DMA_SCR_DIR_MASK)) == (DMA_SCR_CIRC | DMA_SCR_DIR_P2M)))
+ {
+ regval |= (DMA_SFCR_FTH_FULL | DMA_SFCR_DMDIS);
+ }
+ dmast_putreg(dmast, STM32_DMA_SFCR_OFFSET, regval);
+
+ /* "Configure data transfer direction, circular mode, peripheral & memory
+ * incremented mode, peripheral & memory data size, and interrupt after
+ * half and/or full transfer in the DMA_CCRx register."
+ *
+ * Note: The CT bit is always reset.
+ */
+
+ regval = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ regval &= ~(DMA_SCR_PFCTRL|DMA_SCR_DIR_MASK|DMA_SCR_PINC|DMA_SCR_MINC|
+ DMA_SCR_PSIZE_MASK|DMA_SCR_MSIZE_MASK|DMA_SCR_PINCOS|
+ DMA_SCR_CIRC|DMA_SCR_DBM|DMA_SCR_CT|
+ DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK);
+ scr &= (DMA_SCR_PFCTRL|DMA_SCR_DIR_MASK|DMA_SCR_PINC|DMA_SCR_MINC|
+ DMA_SCR_PSIZE_MASK|DMA_SCR_MSIZE_MASK|DMA_SCR_PINCOS|
+ DMA_SCR_DBM|DMA_SCR_CIRC|
+ DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK);
+ regval |= scr;
+ dmast->nonstop = (scr & (DMA_SCR_DBM|DMA_SCR_CIRC)) != 0;
+ dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: stm32_dmastart
+ *
+ * Description:
+ * Start the DMA transfer
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ * - No DMA in progress
+ *
+ ****************************************************************************/
+
+void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool half)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ uint32_t scr;
+
+ DEBUGASSERT(handle != NULL);
+
+ /* Save the callback info. This will be invoked whent the DMA commpletes */
+
+ dmast->callback = callback;
+ dmast->arg = arg;
+
+ /* Activate the stream by setting the ENABLE bit in the DMA_SCRx register.
+ * As soon as the stream is enabled, it can serve any DMA request from the
+ * peripheral connected on the stream.
+ */
+
+ scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ scr |= DMA_SCR_EN;
+
+ if (!dmast->nonstop)
+ {
+ /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
+ * set and an interrupt is generated if the Half-Transfer Interrupt Enable
+ * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
+ * (TCIF) is set and an interrupt is generated if the Transfer Complete
+ * Interrupt Enable bit (TCIE) is set.
+ */
+
+ scr |= (half ? (DMA_SCR_HTIE|DMA_SCR_TEIE) : (DMA_SCR_TCIE|DMA_SCR_TEIE));
+ }
+ else
+ {
+ /* In nonstop mode, when the transfer completes it immediately resets
+ * and starts again. The transfer-complete interrupt is thus always
+ * enabled, and the half-complete interrupt can be used in circular
+ * mode to determine when the buffer is half-full, or in double-buffered
+ * mode to determine when one of the two buffers is full.
+ */
+ scr |= (half ? DMA_SCR_HTIE : 0) | DMA_SCR_TCIE | DMA_SCR_TEIE;
+ }
+
+ dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, scr);
+}
+
+/****************************************************************************
+ * Name: stm32_dmastop
+ *
+ * Description:
+ * Cancel the DMA. After stm32_dmastop() is called, the DMA channel is
+ * reset and stm32_dmasetup() must be called before stm32_dmastart() can be
+ * called again
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+void stm32_dmastop(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ stm32_dmastreamdisable(dmast);
+}
+
+/****************************************************************************
+ * Name: stm32_dmaresidual
+ *
+ * Description:
+ * Read the DMA bytes-remaining register.
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+size_t stm32_dmaresidual(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ uint32_t residual;
+
+ /* Fetch the count of bytes remaining to be transferred.
+ *
+ * If the FIFO is enabled, this count may be inaccurate. ST don't
+ * appear to document whether this counts the peripheral or the memory
+ * side of the channel, and they don't make the memory pointer
+ * available either.
+ *
+ * For reception in circular mode the FIFO is disabled in order that
+ * this value can be useful.
+ */
+
+ residual = dmast_getreg(dmast, STM32_DMA_SNDTR_OFFSET);
+
+ return (size_t)residual;
+}
+
+/****************************************************************************
+ * Name: stm32_dmasample
+ *
+ * Description:
+ * Sample DMA register contents
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_DMA
+void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ irqstate_t flags;
+
+ flags = irqsave();
+ regs->lisr = dmabase_getreg(dmast, STM32_DMA_LISR_OFFSET);
+ regs->hisr = dmabase_getreg(dmast, STM32_DMA_HISR_OFFSET);
+ regs->scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
+ regs->sndtr = dmast_getreg(dmast, STM32_DMA_SNDTR_OFFSET);
+ regs->spar = dmast_getreg(dmast, STM32_DMA_SPAR_OFFSET);
+ regs->sm0ar = dmast_getreg(dmast, STM32_DMA_SM0AR_OFFSET);
+ regs->sm1ar = dmast_getreg(dmast, STM32_DMA_SM1AR_OFFSET);
+ regs->sfcr = dmast_getreg(dmast, STM32_DMA_SFCR_OFFSET);
+ irqrestore(flags);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32_dmadump
+ *
+ * Description:
+ * Dump previously sampled DMA register contents
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_DMA
+void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs,
+ const char *msg)
+{
+ struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
+ uint32_t dmabase = DMA_BASE(dmast->base);
+
+ dmadbg("DMA Registers: %s\n", msg);
+ dmadbg(" LISR[%08x]: %08x\n", dmabase + STM32_DMA_LISR_OFFSET, regs->lisr);
+ dmadbg(" HISR[%08x]: %08x\n", dmabase + STM32_DMA_HISR_OFFSET, regs->hisr);
+ dmadbg(" SCR[%08x]: %08x\n", dmast->base + STM32_DMA_SCR_OFFSET, regs->scr);
+ dmadbg(" SNDTR[%08x]: %08x\n", dmast->base + STM32_DMA_SNDTR_OFFSET, regs->sndtr);
+ dmadbg(" SPAR[%08x]: %08x\n", dmast->base + STM32_DMA_SPAR_OFFSET, regs->spar);
+ dmadbg(" SM0AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM0AR_OFFSET, regs->sm0ar);
+ dmadbg(" SM1AR[%08x]: %08x\n", dmast->base + STM32_DMA_SM1AR_OFFSET, regs->sm1ar);
+ dmadbg(" SFCR[%08x]: %08x\n", dmast->base + STM32_DMA_SFCR_OFFSET, regs->sfcr);
+}
+#endif
+
+#endif /* CONFIG_STM32_STM32F40XX */
diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c
new file mode 100644
index 000000000..7ba341b2b
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_rcc.c
@@ -0,0 +1,668 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32f40xxx_rcc.c
+ *
+ * Copyright (C) 2011-2012 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 "stm32_pwr.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* Allow up to 100 milliseconds for the high speed clock to become ready.
+ * that is a very long delay, but if the clock does not become ready we are
+ * hosed anyway. Normally this is very fast, but I have seen at least one
+ * board that required this long, long timeout for the HSE to be ready.
+ */
+
+#define HSERDY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rcc_reset
+ *
+ * Description:
+ * Reset the RCC clock configuration to the default reset state
+ *
+ ****************************************************************************/
+
+static inline void rcc_reset(void)
+{
+ uint32_t regval;
+
+ /* Enable the Internal High Speed clock (HSI) */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval |= RCC_CR_HSION;
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Reset CFGR register */
+
+ putreg32(0x00000000, STM32_RCC_CFGR);
+
+ /* Reset HSEON, CSSON and PLLON bits */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval &= ~(RCC_CR_HSEON|RCC_CR_CSSON|RCC_CR_PLLON);
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Reset PLLCFGR register to reset default */
+
+ putreg32(RCC_PLLCFG_RESET, STM32_RCC_PLLCFG);
+
+ /* Reset HSEBYP bit */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval &= ~RCC_CR_HSEBYP;
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Disable all interrupts */
+
+ putreg32(0x00000000, STM32_RCC_CIR);
+}
+
+/****************************************************************************
+ * Name: rcc_enableahb1
+ *
+ * Description:
+ * Enable selected AHB1 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableahb1(void)
+{
+ uint32_t regval;
+
+ /* Set the appropriate bits in the AHB1ENR register to enabled the
+ * selected AHB1 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_AHB1ENR);
+
+ /* Enable GPIOA, GPIOB, .... GPIOI*/
+
+#if STM32_NGPIO > 0
+ regval |= (RCC_AHB1ENR_GPIOAEN
+#if STM32_NGPIO > 16
+ |RCC_AHB1ENR_GPIOBEN
+#endif
+#if STM32_NGPIO > 32
+ |RCC_AHB1ENR_GPIOCEN
+#endif
+#if STM32_NGPIO > 48
+ |RCC_AHB1ENR_GPIODEN
+#endif
+#if STM32_NGPIO > 64
+ |RCC_AHB1ENR_GPIOEEN
+#endif
+#if STM32_NGPIO > 80
+ |RCC_AHB1ENR_GPIOFEN
+#endif
+#if STM32_NGPIO > 96
+ |RCC_AHB1ENR_GPIOGEN
+#endif
+#if STM32_NGPIO > 112
+ |RCC_AHB1ENR_GPIOHEN
+#endif
+#if STM32_NGPIO > 128
+ |RCC_AHB1ENR_GPIOIEN
+#endif
+ );
+#endif
+
+#ifdef CONFIG_STM32_CRC
+ /* CRC clock enable */
+
+ regval |= RCC_AHB1ENR_CRCEN;
+#endif
+
+#ifdef CONFIG_STM32_BKPSRAM
+ /* Backup SRAM clock enable */
+
+ regval |= RCC_AHB1ENR_BKPSRAMEN;
+#endif
+
+#ifdef CONFIG_STM32_CCMDATARAM
+ /* CCM data RAM clock enable */
+
+ regval |= RCC_AHB1ENR_CCMDATARAMEN;
+#endif
+
+#ifdef CONFIG_STM32_DMA1
+ /* DMA 1 clock enable */
+
+ regval |= RCC_AHB1ENR_DMA1EN;
+#endif
+
+#ifdef CONFIG_STM32_DMA2
+ /* DMA 2 clock enable */
+
+ regval |= RCC_AHB1ENR_DMA2EN;
+#endif
+
+#ifdef CONFIG_STM32_ETHMAC
+ /* Ethernet MAC clocking */
+
+ regval |= (RCC_AHB1ENR_ETHMACEN|RCC_AHB1ENR_ETHMACTXEN|RCC_AHB1ENR_ETHMACRXEN);
+
+#ifdef CONFIG_STM32_ETH_PTP
+ /* Precision Time Protocol (PTP) */
+
+ regval |= RCC_AHB1ENR_ETHMACPTPEN;
+
+#endif
+#endif
+
+#ifdef CONFIG_STM32_OTGHS
+ /* USB OTG HS */
+
+ regval |= (RCC_AHB1ENR_OTGHSEN|RCC_AHB1ENR_OTGHSULPIEN);
+#endif
+
+ putreg32(regval, STM32_RCC_AHB1ENR); /* Enable peripherals */
+}
+
+/****************************************************************************
+ * Name: rcc_enableahb2
+ *
+ * Description:
+ * Enable selected AHB2 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableahb2(void)
+{
+ uint32_t regval;
+
+ /* Set the appropriate bits in the AHB2ENR register to enabled the
+ * selected AHB2 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_AHB2ENR);
+
+#ifdef CONFIG_STM32_DCMI
+ /* Camera interface enable */
+
+ regval |= RCC_AHB2ENR_DCMIEN;
+#endif
+
+#ifdef CONFIG_STM32_CRYP
+ /* Cryptographic modules clock enable */
+
+ regval |= RCC_AHB2ENR_CRYPEN;
+#endif
+
+#ifdef CONFIG_STM32_HASH
+ /* Hash modules clock enable */
+
+ regval |= RCC_AHB2ENR_HASHEN;
+#endif
+
+#ifdef CONFIG_STM32_RNG
+ /* Random number generator clock enable */
+
+ regval |= RCC_AHB2ENR_RNGEN;
+#endif
+
+#ifdef CONFIG_STM32_OTGFS
+ /* USB OTG FS clock enable */
+
+ regval |= RCC_AHB2ENR_OTGFSEN;
+#endif
+
+ putreg32(regval, STM32_RCC_AHB2ENR); /* Enable peripherals */
+}
+
+/****************************************************************************
+ * Name: rcc_enableahb3
+ *
+ * Description:
+ * Enable selected AHB3 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableahb3(void)
+{
+#ifdef CONFIG_STM32_FSMC
+ uint32_t regval;
+
+ /* Set the appropriate bits in the AHB3ENR register to enabled the
+ * selected AHB3 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_AHB3ENR);
+
+ /* Flexible static memory controller module clock enable */
+
+ regval |= RCC_AHB3ENR_FSMCEN;
+
+ putreg32(regval, STM32_RCC_AHB3ENR); /* Enable peripherals */
+#endif
+}
+
+/****************************************************************************
+ * Name: rcc_enableapb1
+ *
+ * Description:
+ * Enable selected APB1 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableapb1(void)
+{
+ uint32_t regval;
+
+ /* Set the appropriate bits in the APB1ENR register to enabled the
+ * selected APB1 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_APB1ENR);
+
+#ifdef CONFIG_STM32_TIM2
+ /* TIM2 clock enable */
+
+ regval |= RCC_APB1ENR_TIM2EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM3
+ /* TIM3 clock enable */
+
+ regval |= RCC_APB1ENR_TIM3EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM4
+ /* TIM4 clock enable */
+
+ regval |= RCC_APB1ENR_TIM4EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM5
+ /* TIM5 clock enable */
+
+ regval |= RCC_APB1ENR_TIM5EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM6
+ /* TIM6 clock enable */
+
+ regval |= RCC_APB1ENR_TIM6EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM7
+ /* TIM7 clock enable */
+
+ regval |= RCC_APB1ENR_TIM7EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM12
+ /* TIM12 clock enable */
+
+ regval |= RCC_APB1ENR_TIM12EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM13
+ /* TIM13 clock enable */
+
+ regval |= RCC_APB1ENR_TIM13EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM14
+ /* TIM14 clock enable */
+
+ regval |= RCC_APB1ENR_TIM14EN;
+#endif
+
+#ifdef CONFIG_STM32_WWDG
+ /* Window watchdog clock enable */
+
+ regval |= RCC_APB1ENR_WWDGEN;
+#endif
+
+#ifdef CONFIG_STM32_SPI2
+ /* SPI2 clock enable */
+
+ regval |= RCC_APB1ENR_SPI2EN;
+#endif
+
+#ifdef CONFIG_STM32_SPI3
+ /* SPI3 clock enable */
+
+ regval |= RCC_APB1ENR_SPI3EN;
+#endif
+
+#ifdef CONFIG_STM32_USART2
+ /* USART 2 clock enable */
+
+ regval |= RCC_APB1ENR_USART2EN;
+#endif
+
+#ifdef CONFIG_STM32_USART3
+ /* USART3 clock enable */
+
+ regval |= RCC_APB1ENR_USART3EN;
+#endif
+
+#ifdef CONFIG_STM32_UART4
+ /* UART4 clock enable */
+
+ regval |= RCC_APB1ENR_UART4EN;
+#endif
+
+#ifdef CONFIG_STM32_UART5
+ /* UART5 clock enable */
+
+ regval |= RCC_APB1ENR_UART5EN;
+#endif
+
+#ifdef CONFIG_STM32_I2C1
+ /* I2C1 clock enable */
+
+ regval |= RCC_APB1ENR_I2C1EN;
+#endif
+
+#ifdef CONFIG_STM32_I2C2
+ /* I2C2 clock enable */
+
+ regval |= RCC_APB1ENR_I2C2EN;
+#endif
+
+#ifdef CONFIG_STM32_I2C3
+ /* I2C3 clock enable */
+
+ regval |= RCC_APB1ENR_I2C3EN;
+#endif
+
+#ifdef CONFIG_STM32_CAN1
+ /* CAN 1 clock enable */
+
+ regval |= RCC_APB1ENR_CAN1EN;
+#endif
+
+#ifdef CONFIG_STM32_CAN2
+ /* CAN2 clock enable. NOTE: CAN2 needs CAN1 clock as well. */
+
+ regval |= (RCC_APB1ENR_CAN1EN | RCC_APB1ENR_CAN2EN);
+#endif
+
+ /* Power interface clock enable. The PWR block is always enabled so that
+ * we can set the internal voltage regulator for maximum performance.
+ */
+
+ regval |= RCC_APB1ENR_PWREN;
+
+#if defined (CONFIG_STM32_DAC1) || defined(CONFIG_STM32_DAC2)
+ /* DAC interface clock enable */
+
+ regval |= RCC_APB1ENR_DACEN;
+#endif
+
+ putreg32(regval, STM32_RCC_APB1ENR); /* Enable peripherals */
+}
+
+/****************************************************************************
+ * Name: rcc_enableapb2
+ *
+ * Description:
+ * Enable selected APB2 peripherals
+ *
+ ****************************************************************************/
+
+static inline void rcc_enableapb2(void)
+{
+ uint32_t regval;
+
+ /* Set the appropriate bits in the APB2ENR register to enabled the
+ * selected APB2 peripherals.
+ */
+
+ regval = getreg32(STM32_RCC_APB2ENR);
+
+#ifdef CONFIG_STM32_TIM1
+ /* TIM1 clock enable */
+
+ regval |= RCC_APB2ENR_TIM1EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM8
+ /* TIM8 clock enable */
+
+ regval |= RCC_APB2ENR_TIM8EN;
+#endif
+
+#ifdef CONFIG_STM32_USART1
+ /* USART1 clock enable */
+
+ regval |= RCC_APB2ENR_USART1EN;
+#endif
+
+#ifdef CONFIG_STM32_USART6
+ /* USART6 clock enable */
+
+ regval |= RCC_APB2ENR_USART6EN;
+#endif
+
+#ifdef CONFIG_STM32_ADC1
+ /* ADC1 clock enable */
+
+ regval |= RCC_APB2ENR_ADC1EN;
+#endif
+
+#ifdef CONFIG_STM32_ADC2
+ /* ADC2 clock enable */
+
+ regval |= RCC_APB2ENR_ADC2EN;
+#endif
+
+#ifdef CONFIG_STM32_ADC3
+ /* ADC3 clock enable */
+
+ regval |= RCC_APB2ENR_ADC3EN;
+#endif
+
+#ifdef CONFIG_STM32_SDIO
+ /* SDIO clock enable */
+
+ regval |= RCC_APB2ENR_SDIOEN;
+#endif
+
+#ifdef CONFIG_STM32_SPI1
+ /* SPI1 clock enable */
+
+ regval |= RCC_APB2ENR_SPI1EN;
+#endif
+
+#ifdef CONFIG_STM32_SYSCFG
+ /* System configuration controller clock enable */
+
+ regval |= RCC_APB2ENR_SYSCFGEN;
+#endif
+
+#ifdef CONFIG_STM32_TIM9
+ /* TIM9 clock enable */
+
+ regval |= RCC_APB2ENR_TIM9EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM10
+ /* TIM10 clock enable */
+
+ regval |= RCC_APB2ENR_TIM10EN;
+#endif
+
+#ifdef CONFIG_STM32_TIM11
+ /* TIM11 clock enable */
+
+ regval |= RCC_APB2ENR_TIM11EN;
+#endif
+
+ putreg32(regval, STM32_RCC_APB2ENR); /* Enable peripherals */
+}
+
+/****************************************************************************
+ * Name: stm32_stdclockconfig
+ *
+ * Description:
+ * Called to change to new clock based on settings in board.h
+ *
+ * NOTE: This logic would need to be extended if you need to select low-
+ * power clocking modes!
+ ****************************************************************************/
+
+#ifndef CONFIG_ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG
+static void stm32_stdclockconfig(void)
+{
+ uint32_t regval;
+ volatile int32_t timeout;
+
+ /* Enable External High-Speed Clock (HSE) */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval |= RCC_CR_HSEON; /* Enable HSE */
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Wait until the HSE is ready (or until a timeout elapsed) */
+
+ for (timeout = HSERDY_TIMEOUT; timeout > 0; timeout--)
+ {
+ /* Check if the HSERDY flag is the set in the CR */
+
+ if ((getreg32(STM32_RCC_CR) & RCC_CR_HSERDY) != 0)
+ {
+ /* If so, then break-out with timeout > 0 */
+
+ break;
+ }
+ }
+
+ /* Check for a timeout. If this timeout occurs, then we are hosed. We
+ * have no real back-up plan, although the following logic makes it look
+ * as though we do.
+ */
+
+ if (timeout > 0)
+ {
+ /* Select regulator voltage output Scale 1 mode to support system
+ * frequencies up to 168 MHz.
+ */
+
+ regval = getreg32(STM32_RCC_APB1ENR);
+ regval |= RCC_APB1ENR_PWREN;
+ putreg32(regval, STM32_RCC_APB1ENR);
+
+ regval = getreg32(STM32_PWR_CR);
+ regval |= PWR_CR_VOS;
+ putreg32(regval, STM32_PWR_CR);
+
+ /* Set the HCLK source/divider */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_HPRE_MASK;
+ regval |= STM32_RCC_CFGR_HPRE;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Set the PCLK2 divider */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_PPRE2_MASK;
+ regval |= STM32_RCC_CFGR_PPRE2;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Set the PCLK1 divider */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_PPRE1_MASK;
+ regval |= STM32_RCC_CFGR_PPRE1;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Set the PLL dividers and multiplers to configure the main PLL */
+
+ regval = (STM32_PLLCFG_PLLM | STM32_PLLCFG_PLLN |STM32_PLLCFG_PLLP |
+ RCC_PLLCFG_PLLSRC_HSE | STM32_PLLCFG_PPQ);
+ putreg32(regval, STM32_RCC_PLLCFG);
+
+ /* Enable the main PLL */
+
+ regval = getreg32(STM32_RCC_CR);
+ regval |= RCC_CR_PLLON;
+ putreg32(regval, STM32_RCC_CR);
+
+ /* Wait until the PLL is ready */
+
+ while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLRDY) == 0);
+
+ /* Enable FLASH prefetch, instruction cache, data cache, and 5 wait states */
+
+ regval = (FLASH_ACR_LATENCY_5 | FLASH_ACR_ICEN | FLASH_ACR_DCEN);
+ putreg32(regval, STM32_FLASH_ACR);
+
+ /* Select the main PLL as system clock source */
+
+ regval = getreg32(STM32_RCC_CFGR);
+ regval &= ~RCC_CFGR_SW_MASK;
+ regval |= RCC_CFGR_SW_PLL;
+ putreg32(regval, STM32_RCC_CFGR);
+
+ /* Wait until the PLL source is used as the system clock source */
+
+ while ((getreg32(STM32_RCC_CFGR) & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: rcc_enableperiphals
+ ****************************************************************************/
+
+static inline void rcc_enableperipherals(void)
+{
+ rcc_enableahb1();
+ rcc_enableahb2();
+ rcc_enableahb3();
+ rcc_enableapb1();
+ rcc_enableapb2();
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c
new file mode 100644
index 000000000..c11748ae5
--- /dev/null
+++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_rtc.c
@@ -0,0 +1,842 @@
+/************************************************************************************
+ * arch/arm/src/stm32/stm32f40xxx_rtc.c
+ *
+ * Copyright (C) 2011 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 <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/rtc.h>
+
+#include <time.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+
+#include "stm32_rtc.h"
+
+#ifdef CONFIG_RTC
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+/* Configuration ********************************************************************/
+/* This RTC implementation supports only date/time RTC hardware */
+
+#ifndef CONFIG_RTC_DATETIME
+# error "CONFIG_RTC_DATETIME must be set to use this driver"
+#endif
+
+#ifdef CONFIG_RTC_HIRES
+# error "CONFIG_RTC_HIRES must NOT be set with this driver"
+#endif
+
+#ifndef CONFIG_STM32_PWR
+# error "CONFIG_STM32_PWR must selected to use this driver"
+#endif
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_DEBUG_RTC
+#endif
+
+/* Constants ************************************************************************/
+
+#define SYNCHRO_TIMEOUT (0x00020000)
+#define INITMODE_TIMEOUT (0x00010000)
+#define RTC_MAGIC (0xfacefeed)
+#define RTC_PREDIV_S (0xff)
+#define RTC_PREDIV_A (0x7f)
+
+/* Debug ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_RTC
+# define rtcdbg dbg
+# define rtcvdbg vdbg
+# define rtclldbg lldbg
+# define rtcllvdbg llvdbg
+#else
+# define rtcdbg(x...)
+# define rtcvdbg(x...)
+# define rtclldbg(x...)
+# define rtcllvdbg(x...)
+#endif
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Private Data
+ ************************************************************************************/
+
+/* Callback to use when the alarm expires */
+
+#ifdef CONFIG_RTC_ALARM
+static alarmcb_t g_alarmcb;
+#endif
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/* g_rtc_enabled is set true after the RTC has successfully initialized */
+
+volatile bool g_rtc_enabled = false;
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+/************************************************************************************
+ * Name: rtc_dumpregs
+ *
+ * Description:
+ * Disable RTC write protection
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_DEBUG_RTC
+static void rtc_dumpregs(FAR const char *msg)
+{
+ rtclldbg("%s:\n", msg);
+ rtclldbg(" TR: %08x\n", getreg32(STM32_RTC_TR));
+ rtclldbg(" DR: %08x\n", getreg32(STM32_RTC_DR));
+ rtclldbg(" CR: %08x\n", getreg32(STM32_RTC_CR));
+ rtclldbg(" ISR: %08x\n", getreg32(STM32_RTC_ISR));
+ rtclldbg(" PRER: %08x\n", getreg32(STM32_RTC_PRER));
+ rtclldbg(" WUTR: %08x\n", getreg32(STM32_RTC_WUTR));
+ rtclldbg(" CALIBR: %08x\n", getreg32(STM32_RTC_CALIBR));
+ rtclldbg(" ALRMAR: %08x\n", getreg32(STM32_RTC_ALRMAR));
+ rtclldbg(" ALRMBR: %08x\n", getreg32(STM32_RTC_ALRMBR));
+ rtclldbg(" SHIFTR: %08x\n", getreg32(STM32_RTC_SHIFTR));
+ rtclldbg(" TSTR: %08x\n", getreg32(STM32_RTC_TSTR));
+ rtclldbg(" TSDR: %08x\n", getreg32(STM32_RTC_TSDR));
+ rtclldbg(" TSSSR: %08x\n", getreg32(STM32_RTC_TSSSR));
+ rtclldbg(" CALR: %08x\n", getreg32(STM32_RTC_CALR));
+ rtclldbg(" TAFCR: %08x\n", getreg32(STM32_RTC_TAFCR));
+ rtclldbg("ALRMASSR: %08x\n", getreg32(STM32_RTC_ALRMASSR));
+ rtclldbg("ALRMBSSR: %08x\n", getreg32(STM32_RTC_ALRMBSSR));
+ rtclldbg(" BK0: %08x\n", getreg32(STM32_RTC_BK0R));
+}
+#else
+# define rtc_dumpregs(msg)
+#endif
+
+/************************************************************************************
+ * Name: rtc_dumptime
+ *
+ * Description:
+ * Disable RTC write protection
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_DEBUG_RTC
+static void rtc_dumptime(FAR struct tm *tp, FAR const char *msg)
+{
+ rtclldbg("%s:\n", msg);
+ rtclldbg(" tm_sec: %08x\n", tp->tm_sec);
+ rtclldbg(" tm_min: %08x\n", tp->tm_min);
+ rtclldbg(" tm_hour: %08x\n", tp->tm_hour);
+ rtclldbg(" tm_mday: %08x\n", tp->tm_mday);
+ rtclldbg(" tm_mon: %08x\n", tp->tm_mon);
+ rtclldbg(" tm_year: %08x\n", tp->tm_year);
+}
+#else
+# define rtc_dumptime(tp, msg)
+#endif
+
+/************************************************************************************
+ * Name: rtc_wprunlock
+ *
+ * Description:
+ * Disable RTC write protection
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static void rtc_wprunlock(void)
+{
+ /* The following steps are required to unlock the write protection on all the
+ * RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR).
+ *
+ * 1. Write 0xCA into the RTC_WPR register.
+ * 2. Write 0x53 into the RTC_WPR register.
+ *
+ * Writing a wrong key reactivates the write protection.
+ */
+
+ putreg32(0xca, STM32_RTC_WPR);
+ putreg32(0x53, STM32_RTC_WPR);
+}
+
+/************************************************************************************
+ * Name: rtc_wprunlock
+ *
+ * Description:
+ * Enable RTC write protection
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ************************************************************************************/
+
+static inline void rtc_wprlock(void)
+{
+ /* Writing any wrong key reactivates the write protection. */
+
+ putreg32(0xff, STM32_RTC_WPR);
+}
+
+/************************************************************************************
+ * Name: rtc_synchwait
+ *
+ * Description:
+ * Waits until the RTC Time and Date registers (RTC_TR and RTC_DR) are
+ * synchronized with RTC APB clock.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static int rtc_synchwait(void)
+{
+ volatile uint32_t timeout;
+ uint32_t regval;
+ int ret;
+
+ /* Disable the write protection for RTC registers */
+
+ rtc_wprunlock();
+
+ /* Clear Registers synchronization flag (RSF) */
+
+ regval = getreg32(STM32_RTC_ISR);
+ regval &= ~RTC_ISR_RSF;
+ putreg32(regval, STM32_RTC_ISR);
+
+ /* Now wait the registers to become synchronised */
+
+ ret = -ETIMEDOUT;
+ for (timeout = 0; timeout < SYNCHRO_TIMEOUT; timeout++)
+ {
+ regval = getreg32(STM32_RTC_ISR);
+ if ((regval & RTC_ISR_RSF) != 0)
+ {
+ /* Synchronized */
+
+ ret = OK;
+ break;
+ }
+ }
+
+ /* Re-enable the write protection for RTC registers */
+
+ rtc_wprlock();
+ return ret;
+}
+
+/************************************************************************************
+ * Name: rtc_enterinit
+ *
+ * Description:
+ * Enter RTC initialization mode.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static int rtc_enterinit(void)
+{
+ volatile uint32_t timeout;
+ uint32_t regval;
+ int ret;
+
+ /* Check if the Initialization mode is already set */
+
+ regval = getreg32(STM32_RTC_ISR);
+
+ ret = OK;
+ if ((regval & RTC_ISR_INITF) == 0)
+ {
+ /* Set the Initialization mode */
+
+ putreg32(RTC_ISR_INIT, STM32_RTC_ISR);
+
+ /* Wait until the RTC is in the INIT state (or a timeout occurs) */
+
+ ret = -ETIMEDOUT;
+ for (timeout = 0; timeout < INITMODE_TIMEOUT; timeout++)
+ {
+ regval = getreg32(STM32_RTC_ISR);
+ if ((regval & RTC_ISR_INITF) != 0)
+ {
+ ret = OK;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/************************************************************************************
+ * Name: rtc_exitinit
+ *
+ * Description:
+ * Exit RTC initialization mode.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static void rtc_exitinit(void)
+{
+ uint32_t regval;
+
+ regval = getreg32(STM32_RTC_ISR);
+ regval &= ~(RTC_ISR_INIT);
+ putreg32(regval, STM32_RTC_ISR);
+}
+
+/************************************************************************************
+ * Name: rtc_bin2bcd
+ *
+ * Description:
+ * Converts a 2 digit binary to BCD format
+ *
+ * Input Parameters:
+ * value - The byte to be converted.
+ *
+ * Returned Value:
+ * The value in BCD representation
+ *
+ ************************************************************************************/
+
+static uint32_t rtc_bin2bcd(int value)
+{
+ uint32_t msbcd = 0;
+
+ while (value >= 10)
+ {
+ msbcd++;
+ value -= 10;
+ }
+
+ return (msbcd << 4) | value;
+}
+
+/************************************************************************************
+ * Name: rtc_bin2bcd
+ *
+ * Description:
+ * Convert from 2 digit BCD to binary.
+ *
+ * Input Parameters:
+ * value - The BCD value to be converted.
+ *
+ * Returned Value:
+ * The value in binary representation
+ *
+ ************************************************************************************/
+
+static int rtc_bcd2bin(uint32_t value)
+{
+ uint32_t tens = (value >> 4) * 10;
+ return (int)(tens + (value & 0x0f));
+}
+
+/************************************************************************************
+ * Name: rtc_setup
+ *
+ * Description:
+ * Performs first time configuration of the RTC. A special value written into
+ * back-up register 0 will prevent this function from being called on sub-sequent
+ * resets or power up.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static int rtc_setup(void)
+{
+ uint32_t regval;
+ int ret;
+
+ /* Enable the External Low-Speed (LSE) Oscillator setup the LSE as the RTC clock\
+ * source, and enable the RTC.
+ */
+
+ stm32_rcc_enablelse();
+
+ /* Wait for the RTC Time and Date registers to be synchronized with RTC APB
+ * clock.
+ */
+
+ ret = rtc_synchwait();
+ if (ret == OK)
+ {
+ /* Disable the write protection for RTC registers */
+
+ rtc_wprunlock();
+
+ /* Set Initialization mode */
+
+ ret = rtc_enterinit();
+ if (ret == OK)
+ {
+ /* Set the 24 hour format by clearing the FMT bit in the RTC
+ * control register
+ */
+
+ regval = getreg32(STM32_RTC_CR);
+ regval &= ~RTC_CR_FMT;
+ putreg32(regval, STM32_RTC_CR);
+
+ /* Configure RTC pre-scaler to the required, default values for
+ * use with the 32.768 KHz LSE clock:
+ */
+
+ putreg32(((uint32_t)0xff << RTC_PRER_PREDIV_S_SHIFT) |
+ ((uint32_t)0x7f << RTC_PRER_PREDIV_A_SHIFT),
+ STM32_RTC_PRER);
+
+ /* Exit RTC initialization mode */
+
+ rtc_exitinit();
+ }
+
+ /* Re-enable the write protection for RTC registers */
+
+ rtc_wprlock();
+ }
+ return ret;
+}
+
+/************************************************************************************
+ * Name: rtc_resume
+ *
+ * Description:
+ * Called when the RTC was already initialized on a previous power cycle. This
+ * just brings the RTC back into full operation.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+static int rtc_resume(void)
+{
+#ifdef CONFIG_RTC_ALARM
+ uint32_t regval;
+#endif
+ int ret;
+
+ /* Wait for the RTC Time and Date registers to be syncrhonized with RTC APB
+ * clock.
+ */
+
+ ret = rtc_synchwait();
+
+ /* Clear the RTC alarm flags */
+
+#ifdef CONFIG_RTC_ALARM
+ regval = getreg32(STM32_RTC_ISR);
+ regval &= ~(RTC_ISR_ALRAF|RTC_ISR_ALRBF);
+ putreg32(regval, STM32_RTC_ISR);
+
+ /* Clear the EXTI Line 17 Pending bit (Connected internally to RTC Alarm) */
+
+ putreg32((1 << 17), STM32_EXTI_PR);
+#endif
+ return ret;
+}
+
+/************************************************************************************
+ * Name: rtc_interrupt
+ *
+ * Description:
+ * RTC interrupt service routine
+ *
+ * Input Parameters:
+ * irq - The IRQ number that generated the interrupt
+ * context - Architecture specific register save information.
+ *
+ * Returned Value:
+ * Zero (OK) on success; A negated errno value on failure.
+ *
+ ************************************************************************************/
+
+#if CONFIG_RTC_ALARM
+static int rtc_interrupt(int irq, void *context)
+{
+#warning "Missing logic"
+ return OK;
+}
+#endif
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: up_rtcinitialize
+ *
+ * Description:
+ * Initialize the hardware RTC per the selected configuration. This function is
+ * called once during the OS initialization sequence
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtcinitialize(void)
+{
+ uint32_t regval;
+ int ret;
+
+ rtc_dumpregs("On reset");
+
+ /* Clocking for the PWR block must be provided. However, this is done
+ * unconditionally in stm32f40xxx_rcc.c on power up. This done unconditionally
+ * because the PWR block is also needed to set the internal voltage regulator for
+ * maximum performance.
+ */
+
+ /* Enable access to the backup domain (RTC registers, RTC backup data registers
+ * and backup SRAM).
+ */
+
+ stm32_pwr_enablebkp();
+
+ /* Check if the one-time initialization of the RTC has already been performed.
+ * We can determine this by checking if the magic number has been writing to
+ * to back-up date register DR0.
+ */
+
+ regval = getreg32(STM32_RTC_BK0R);
+ if (regval != RTC_MAGIC)
+ {
+ /* Perform the one-time setup of the LSE clocking to the RTC */
+
+ ret = rtc_setup();
+
+ /* Remember that the RTC is initialized */
+
+ putreg32(RTC_MAGIC, STM32_RTC_BK0R);
+ }
+ else
+ {
+ /* RTC already set-up, just resume normal operation */
+
+ ret = rtc_resume();
+ }
+
+ /* Configure RTC interrupt to catch alarm interrupts. All RTC interrupts are
+ * connected to the EXTI controller. To enable the RTC Alarm interrupt, the
+ * following sequence is required:
+ *
+ * 1. Configure and enable the EXTI Line 17 in interrupt mode and select the
+ * rising edge sensitivity.
+ * 2. Configure and enable the RTC_Alarm IRQ channel in the NVIC.
+ * 3. Configure the RTC to generate RTC alarms (Alarm A or Alarm B).
+ */
+
+#ifdef CONFIG_RTC_ALARM
+# warning "Missing EXTI setup logic"
+
+ /* Then attach the ALARM interrupt handler */
+
+ irq_attach(STM32_IRQ_RTC_WKUP, rtc_interrupt);
+ up_enable_irq(STM32_IRQ_RTC_WKUP);
+#endif
+
+ g_rtc_enabled = true;
+ rtc_dumpregs("After Initialization");
+ return OK;
+}
+
+/************************************************************************************
+ * Name: up_rtc_getdatetime
+ *
+ * Description:
+ * Get the current date and time from the date/time RTC. This interface
+ * is only supported by the date/time RTC hardware implementation.
+ * It is used to replace the system timer. It is only used by the RTOS during
+ * intialization to set up the system time when CONFIG_RTC and CONFIG_RTC_DATETIME
+ * are selected (and CONFIG_RTC_HIRES is not).
+ *
+ * NOTE: Some date/time RTC hardware is capability of sub-second accuracy. That
+ * sub-second accuracy is lost in this interface. However, since the system time
+ * is reinitialized on each power-up/reset, there will be no timing inaccuracy in
+ * the long run.
+ *
+ * Input Parameters:
+ * tp - The location to return the high resolution time value.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtc_getdatetime(FAR struct tm *tp)
+{
+ uint32_t dr;
+ uint32_t tr;
+ uint32_t tmp;
+
+ /* Sample the data time registers. There is a race condition here... If we sample
+ * the time just before midnight on December 31, the date could be wrong because
+ * the day rolled over while were sampling.
+ */
+
+ do
+ {
+ dr = getreg32(STM32_RTC_DR);
+ tr = getreg32(STM32_RTC_TR);
+ tmp = getreg32(STM32_RTC_DR);
+ }
+ while (tmp != dr);
+
+ rtc_dumpregs("Reading Time");
+
+ /* Convert the RTC time to fields in struct tm format. All of the STM32
+ * All of the ranges of values correspond between struct tm and the time
+ * register.
+ */
+
+ tmp = (tr & (RTC_TR_SU_MASK|RTC_TR_ST_MASK)) >> RTC_TR_SU_SHIFT;
+ tp->tm_sec = rtc_bcd2bin(tmp);
+
+ tmp = (tr & (RTC_TR_MNU_MASK|RTC_TR_MNT_MASK)) >> RTC_TR_MNU_SHIFT;
+ tp->tm_min = rtc_bcd2bin(tmp);
+
+ tmp = (tr & (RTC_TR_HU_MASK|RTC_TR_HT_MASK)) >> RTC_TR_HU_SHIFT;
+ tp->tm_hour = rtc_bcd2bin(tmp);
+
+ /* Now convert the RTC date to fields in struct tm format:
+ * Days: 1-31 match in both cases.
+ * Month: STM32 is 1-12, struct tm is 0-11.
+ * Years: STM32 is 00-99, struct tm is years since 1900.
+ *
+ * Issue: I am not sure what the STM32 years mean. Are these the
+ * years 2000-2099? I'll assume so.
+ */
+
+ tmp = (dr & (RTC_DR_DU_MASK|RTC_DR_DT_MASK)) >> RTC_DR_DU_SHIFT;
+ tp->tm_mday = rtc_bcd2bin(tmp);
+
+ tmp = (dr & (RTC_DR_MU_MASK|RTC_DR_MT)) >> RTC_DR_MU_SHIFT;
+ tp->tm_mon = rtc_bcd2bin(tmp) - 1;
+
+ tmp = (dr & (RTC_DR_YU_MASK|RTC_DR_YT_MASK)) >> RTC_DR_YU_SHIFT;
+ tp->tm_year = rtc_bcd2bin(tmp) + 100;
+
+ rtc_dumptime(tp, "Returning");
+ return OK;
+}
+
+/************************************************************************************
+ * Name: up_rtc_settime
+ *
+ * Description:
+ * Set the RTC to the provided time. All RTC implementations must be able to
+ * set their time based on a standard timespec.
+ *
+ * Input Parameters:
+ * tp - the time to use
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+int up_rtc_settime(FAR const struct timespec *tp)
+{
+ FAR struct tm newtime;
+ uint32_t tr;
+ uint32_t dr;
+ int ret;
+
+ /* Break out the time values (not that the time is set only to units of seconds) */
+
+ (void)gmtime_r(&tp->tv_sec, &newtime);
+ rtc_dumptime(&newtime, "Setting time");
+
+ /* Then write the broken out values to the RTC */
+
+ /* Convert the struct tm format to RTC time register fields. All of the STM32
+ * All of the ranges of values correspond between struct tm and the time
+ * register.
+ */
+
+ tr = (rtc_bin2bcd(newtime.tm_sec) << RTC_TR_SU_SHIFT) |
+ (rtc_bin2bcd(newtime.tm_min) << RTC_TR_MNU_SHIFT) |
+ (rtc_bin2bcd(newtime.tm_hour) << RTC_TR_HU_SHIFT);
+ tr &= ~RTC_TR_RESERVED_BITS;
+
+ /* Now convert the fields in struct tm format to the RTC date register fields:
+ * Days: 1-31 match in both cases.
+ * Month: STM32 is 1-12, struct tm is 0-11.
+ * Years: STM32 is 00-99, struct tm is years since 1900.
+ *
+ * Issue: I am not sure what the STM32 years mean. Are these the
+ * years 2000-2099? I'll assume so.
+ */
+
+ dr = (rtc_bin2bcd(newtime.tm_mday) << RTC_DR_DU_SHIFT) |
+ ((rtc_bin2bcd(newtime.tm_mon + 1)) << RTC_DR_MU_SHIFT) |
+ ((rtc_bin2bcd(newtime.tm_year - 100)) << RTC_DR_YU_SHIFT);
+ dr &= ~RTC_DR_RESERVED_BITS;
+
+ /* Disable the write protection for RTC registers */
+
+ rtc_wprunlock();
+
+ /* Set Initialization mode */
+
+ ret = rtc_enterinit();
+ if (ret == OK)
+ {
+ /* Set the RTC TR and DR registers */
+
+ putreg32(tr, STM32_RTC_TR);
+ putreg32(dr, STM32_RTC_DR);
+
+ /* Exit Initialization mode and wait for the RTC Time and Date
+ * registers to be synchronized with RTC APB clock.
+ */
+
+ rtc_exitinit();
+ ret = rtc_synchwait();
+ }
+
+ /* Re-enable the write protection for RTC registers */
+
+ rtc_wprlock();
+ rtc_dumpregs("New time setting");
+ return ret;
+}
+
+/************************************************************************************
+ * Name: up_rtc_setalarm
+ *
+ * Description:
+ * Set up an alarm. Up to two alarms can be supported (ALARM A and ALARM B).
+ *
+ * Input Parameters:
+ * tp - the time to set the alarm
+ * callback - the function to call when the alarm expires.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
+{
+ irqstate_t flags;
+ int ret = -EBUSY;
+
+ /* Is there already something waiting on the ALARM? */
+
+ if (g_alarmcb == NULL)
+ {
+ /* No.. Save the callback function pointer */
+
+ g_alarmcb = callback;
+
+ /* Break out the time values */
+#warning "Missing logic"
+
+ /* The set the alarm */
+#warning "Missing logic"
+
+ ret = OK;
+ }
+ return ret;
+}
+#endif
+
+#endif /* CONFIG_RTC */
+