Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'wip-family-support'

Merge the long-lived (too long; future changes like these will need to
proceed more incrementally) development branch of libmaple, containing
experimental STM32F2 and STM32F1 value line support, into master.

This required many changes to the structure of the library. The most
important structural reorganizations occurred in:

- 954f9e5: moves public headers to include directories
- 3efa313: uses "series" instead of "family"
- c0d60e3: adds board files to the build system, to make it easier to
  add new boards
- 096d86c: adds build logic for targeting different STM32 series
  (e.g. STM32F1, STM32F2)

This last commit in particular (096d86c) is the basis for the
repartitioning of libmaple into portable sections, which work on all
supported MCUs, and nonportable sections, which are segregated into
separate directories and contain all series-specific code. Moving
existing STM32F1-only code into libmaple/stm32f1 and wirish/stm32f1,
along with adding equivalents under .../stm32f2 directories, was the
principal project of this branch.

Important API changes occur in several places. Existing code is still
expected to work on STM32F1 targets, but there have been many
deprecations. A detailed changelog explaining the situation needs to
be prepared.

F2 and F1 value line support is not complete; the merge is proceeding
prematurely in this respect. We've been getting more libmaple patches
from the community lately, and I'm worried that the merge conflicts
with the old tree structure will become painful to manage.

Conflicts:
	Makefile

Resolved Makefile conflicts manually; this required propagating
-Xlinker usage into support/make/target-config.mk.

Signed-off-by: Marti Bolivar <mbolivar@leaflabs.com>
  • Loading branch information...
commit ccc23369719f8909fe61a8423fdf382582414702 2 parents 7451d1d + 12aecf5
@mbolivar mbolivar authored
Showing with 17,303 additions and 5,417 deletions.
  1. +2 −1  .gitignore
  2. +58 −54 Makefile
  3. +0 −1  README
  4. 0  {support → contrib}/openocd/debug_0.3.cfg
  5. 0  {support → contrib}/openocd/debug_0.4.cfg
  6. 0  {support → contrib}/openocd/flash_0.3.cfg
  7. 0  {support → contrib}/openocd/flash_0.4.cfg
  8. 0  {support/scripts → contrib/openocd}/openocd-wrapper.sh
  9. +1 −1  examples/blinky.cpp
  10. +5 −7 examples/debug-dtrrts.cpp
  11. +1 −1  examples/freertos-blinky.cpp
  12. +3 −3 examples/fsmc-stress-test.cpp
  13. +145 −0 examples/i2c-mcp4725-dac.cpp
  14. +1 −1  examples/mini-exti-test.cpp
  15. +1 −1  examples/qa-slave-shield.cpp
  16. +30 −0 examples/serial-echo.cpp
  17. +1 −1  examples/spi_master.cpp
  18. +3 −3 examples/test-bkp.cpp
  19. +2 −2 examples/test-dac.cpp
  20. +2 −2 examples/test-fsmc.cpp
  21. +1 −1  examples/test-print.cpp
  22. +2 −2 examples/test-ring-buffer-insertion.cpp
  23. +1 −1  examples/test-serial-flush.cpp
  24. +3 −3 examples/test-serialusb.cpp
  25. +1 −1  examples/test-servo.cpp
  26. +1 −1  examples/test-session.cpp
  27. +1 −1  examples/test-spi-roundtrip.cpp
  28. +2 −2 examples/test-systick.cpp
  29. +475 −235 examples/test-timers.cpp
  30. +154 −66 examples/test-usart-dma.cpp
  31. +1 −1  examples/vga-leaf.cpp
  32. +2 −2 examples/vga-scope.cpp
  33. +11 −67 libmaple/adc.c
  34. +11 −17 libmaple/dac.c
  35. +0 −168 libmaple/dac.h
  36. +0 −30 libmaple/delay.h
  37. +33 −330 libmaple/dma.c
  38. +0 −453 libmaple/dma.h
  39. +61 −0 libmaple/dma_private.h
  40. +38 −25 libmaple/exti.c
  41. +34 −0 libmaple/exti_private.h
  42. +8 −14 libmaple/flash.c
  43. +5 −152 libmaple/gpio.c
  44. +216 −272 libmaple/i2c.c
  45. +79 −0 libmaple/i2c_private.h
  46. +79 −114 libmaple/{ → include/libmaple}/adc.h
  47. +15 −7 libmaple/{ → include/libmaple}/bitband.h
  48. +7 −7 libmaple/{ → include/libmaple}/bkp.h
  49. +158 −0 libmaple/include/libmaple/dac.h
  50. +65 −0 libmaple/include/libmaple/delay.h
  51. +444 −0 libmaple/include/libmaple/dma.h
  52. +114 −0 libmaple/include/libmaple/dma_common.h
  53. +76 −12 libmaple/{ → include/libmaple}/exti.h
  54. +106 −0 libmaple/include/libmaple/flash.h
  55. +64 −44 libmaple/{ → include/libmaple}/fsmc.h
  56. +121 −0 libmaple/include/libmaple/gpio.h
  57. +229 −164 libmaple/{ → include/libmaple}/i2c.h
  58. +95 −0 libmaple/include/libmaple/i2c_common.h
  59. +7 −8 libmaple/{ → include/libmaple}/iwdg.h
  60. +14 −7 libmaple/{ → include/libmaple}/libmaple.h
  61. +19 −4 libmaple/{ → include/libmaple}/libmaple_types.h
  62. +155 −0 libmaple/include/libmaple/nvic.h
  63. +43 −13 libmaple/{ → include/libmaple}/pwr.h
  64. +175 −0 libmaple/include/libmaple/rcc.h
  65. +5 −6 libmaple/{ → include/libmaple}/ring_buffer.h
  66. +12 −4 libmaple/{ → include/libmaple}/scb.h
  67. +91 −78 libmaple/{ → include/libmaple}/spi.h
  68. +237 −0 libmaple/include/libmaple/stm32.h
  69. +151 −0 libmaple/include/libmaple/syscfg.h
  70. +7 −9 libmaple/{ → include/libmaple}/systick.h
  71. +372 −274 libmaple/{ → include/libmaple}/timer.h
  72. +209 −50 libmaple/{ → include/libmaple}/usart.h
  73. +6 −6 libmaple/{ → include/libmaple}/usb.h
  74. +5 −5 libmaple/{usb → include/libmaple}/usb_cdcacm.h
  75. +8 −8 libmaple/{ → include/libmaple}/util.h
  76. +2 −2 libmaple/iwdg.c
  77. +19 −15 libmaple/nvic.c
  78. +3 −3 libmaple/pwr.c
  79. +116 −153 libmaple/rcc.c
  80. +67 −0 libmaple/rcc_private.h
  81. +23 −31 libmaple/rules.mk
  82. +4 −80 libmaple/spi.c
  83. +37 −0 libmaple/spi_private.h
  84. +0 −191 libmaple/stm32.h
  85. +45 −0 libmaple/stm32_private.h
  86. +112 −0 libmaple/stm32f1/adc.c
  87. +6 −6 libmaple/{ → stm32f1}/bkp.c
  88. +412 −0 libmaple/stm32f1/dma.c
  89. +32 −0 libmaple/stm32f1/exti.c
  90. +11 −9 libmaple/{ → stm32f1}/fsmc.c
  91. +166 −0 libmaple/stm32f1/gpio.c
  92. +129 −0 libmaple/stm32f1/i2c.c
  93. +254 −0 libmaple/stm32f1/include/series/adc.h
  94. +71 −0 libmaple/stm32f1/include/series/dac.h
  95. +565 −0 libmaple/stm32f1/include/series/dma.h
  96. +46 −0 libmaple/stm32f1/include/series/exti.h
  97. +46 −39 libmaple/{ → stm32f1/include/series}/flash.h
  98. +211 −245 libmaple/{ → stm32f1/include/series}/gpio.h
  99. +85 −0 libmaple/stm32f1/include/series/i2c.h
  100. +57 −125 libmaple/{ → stm32f1/include/series}/nvic.h
  101. +52 −0 libmaple/stm32f1/include/series/pwr.h
  102. +259 −230 libmaple/{ → stm32f1/include/series}/rcc.h
  103. +99 −0 libmaple/stm32f1/include/series/spi.h
  104. +212 −0 libmaple/stm32f1/include/series/stm32.h
  105. +128 −0 libmaple/stm32f1/include/series/timer.h
  106. +76 −0 libmaple/stm32f1/include/series/usart.h
  107. +27 −1 libmaple/stm32f1/{isrs_performance.S → performance/isrs.S}
  108. +27 −1 libmaple/stm32f1/{vector_table_performance.S → performance/vector_table.S}
  109. +164 −0 libmaple/stm32f1/rcc.c
  110. +24 −3 libmaple/stm32f1/rules.mk
  111. +84 −0 libmaple/stm32f1/spi.c
  112. +124 −0 libmaple/stm32f1/timer.c
  113. +170 −0 libmaple/stm32f1/usart.c
  114. +270 −0 libmaple/stm32f1/value/isrs.S
  115. +116 −0 libmaple/stm32f1/value/vector_table.S
  116. +84 −0 libmaple/stm32f2/adc.c
  117. +504 −0 libmaple/stm32f2/dma.c
  118. +33 −0 libmaple/stm32f2/exti.c
  119. +90 −0 libmaple/stm32f2/fsmc.c
  120. +194 −0 libmaple/stm32f2/gpio.c
  121. +331 −0 libmaple/stm32f2/include/series/adc.h
  122. +94 −0 libmaple/stm32f2/include/series/dac.h
  123. +810 −0 libmaple/stm32f2/include/series/dma.h
  124. +46 −0 libmaple/stm32f2/include/series/exti.h
  125. +202 −0 libmaple/stm32f2/include/series/flash.h
  126. +264 −0 libmaple/stm32f2/include/series/gpio.h
  127. +160 −0 libmaple/stm32f2/include/series/nvic.h
  128. +73 −0 libmaple/stm32f2/include/series/pwr.h
  129. +951 −0 libmaple/stm32f2/include/series/rcc.h
  130. +88 −0 libmaple/stm32f2/include/series/spi.h
  131. +77 −0 libmaple/stm32f2/include/series/stm32.h
  132. +176 −0 libmaple/stm32f2/include/series/timer.h
  133. +111 −0 libmaple/stm32f2/include/series/usart.h
  134. +322 −0 libmaple/stm32f2/isrs.S
  135. +175 −0 libmaple/stm32f2/rcc.c
  136. +40 −0 libmaple/stm32f2/rules.mk
  137. +88 −0 libmaple/stm32f2/spi.c
  138. +78 −0 libmaple/stm32f2/syscfg.c
  139. +148 −0 libmaple/stm32f2/timer.c
  140. +204 −0 libmaple/stm32f2/usart.c
  141. +135 −0 libmaple/stm32f2/vector_table.S
  142. +3 −3 libmaple/systick.c
  143. +204 −272 libmaple/timer.c
  144. +235 −0 libmaple/timer_private.h
  145. +6 −138 libmaple/usart.c
  146. +41 −0 libmaple/usart_private.c
  147. +53 −0 libmaple/usart_private.h
  148. +30 −39 libmaple/usb/README
  149. +45 −0 libmaple/usb/rules.mk
  150. +8 −4 libmaple/usb/{ → stm32f1}/usb.c
  151. +13 −13 libmaple/usb/{ → stm32f1}/usb_cdcacm.c
  152. +1 −1  libmaple/usb/{ → stm32f1}/usb_descriptors.h
  153. +1 −0  libmaple/usb/{ → stm32f1}/usb_lib_globals.h
  154. 0  libmaple/usb/{ → stm32f1}/usb_reg_map.c
  155. +2 −2 libmaple/usb/{ → stm32f1}/usb_reg_map.h
  156. +46 −77 libmaple/util.c
  157. +1 −1  libraries/FreeRTOS/MapleFreeRTOS.h
  158. +1 −1  libraries/LiquidCrystal/LiquidCrystal.cpp
  159. +2 −2 libraries/LiquidCrystal/LiquidCrystal.h
  160. +4 −4 libraries/Servo/Servo.cpp
  161. +3 −7 libraries/Servo/Servo.h
  162. +0 −1  libraries/Wire/Wire.cpp
  163. +2 −2 libraries/Wire/Wire.h
  164. +1 −1  main.cpp.example
  165. 0  notes/{dma.txt → dma-stm32f1.txt}
  166. +63 −0 notes/stm32.txt
  167. +12 −6 support/doxygen/Doxyfile
  168. +38 −0 support/doxygen/evil_mangler.awk
  169. +26 −0 support/ld/flash.ld
  170. +31 −0 support/ld/jtag.ld
  171. +0 −24 support/ld/maple/flash.ld
  172. +0 −24 support/ld/maple/jtag.ld
  173. +0 −22 support/ld/maple/ram.ld
  174. +0 −18 support/ld/maple_RET6/flash.ld
  175. +0 −18 support/ld/maple_RET6/jtag.ld
  176. +0 −17 support/ld/maple_RET6/ram.ld
  177. +0 −23 support/ld/maple_mini/flash.ld
  178. +0 −24 support/ld/maple_mini/jtag.ld
  179. +0 −22 support/ld/maple_mini/ram.ld
  180. +0 −22 support/ld/maple_native/flash.ld
  181. +0 −22 support/ld/maple_native/jtag.ld
  182. +0 −20 support/ld/maple_native/ram.ld
  183. +0 −1  support/ld/olimex_stm32_h103
  184. +25 −0 support/ld/ram.ld
  185. +3 −0  support/ld/stm32/mem/maple_native/maple_native_heap.inc
  186. +7 −0 support/ld/stm32/mem/maple_native/mem-flash.inc
  187. +7 −0 support/ld/stm32/mem/maple_native/mem-jtag.inc
  188. +7 −0 support/ld/stm32/mem/maple_native/mem-ram.inc
  189. +5 −0 support/ld/stm32/mem/sram_112k_flash_1024k/mem-jtag.inc
  190. +5 −0 support/ld/stm32/mem/sram_112k_flash_1024k/mem-ram.inc
  191. +5 −0 support/ld/stm32/mem/sram_20k_flash_128k/mem-flash.inc
  192. +5 −0 support/ld/stm32/mem/sram_20k_flash_128k/mem-jtag.inc
  193. +5 −0 support/ld/stm32/mem/sram_20k_flash_128k/mem-ram.inc
  194. +5 −0 support/ld/stm32/mem/sram_64k_flash_512k/mem-flash.inc
  195. +5 −0 support/ld/stm32/mem/sram_64k_flash_512k/mem-jtag.inc
  196. +5 −0 support/ld/stm32/mem/sram_64k_flash_512k/mem-ram.inc
  197. +5 −0 support/ld/stm32/mem/sram_8k_flash_128k/mem-flash.inc
  198. +5 −0 support/ld/stm32/mem/sram_8k_flash_128k/mem-jtag.inc
  199. +5 −0 support/ld/stm32/mem/sram_8k_flash_128k/mem-ram.inc
  200. 0  support/ld/stm32/{f1 → series/stm32f1}/performance/vector_symbols.inc
  201. +78 −0 support/ld/stm32/series/stm32f1/value/vector_symbols.inc
  202. +98 −0 support/ld/stm32/series/stm32f2/vector_symbols.inc
  203. +7 −0 support/make/board-includes/VLDiscovery.mk
  204. +10 −0 support/make/board-includes/maple.mk
  205. +7 −0 support/make/board-includes/maple_RET6.mk
  206. +7 −0 support/make/board-includes/maple_mini.mk
  207. +7 −0 support/make/board-includes/maple_native.mk
  208. +7 −0 support/make/board-includes/olimex_stm32_h103.mk
  209. +5 −0 support/make/board-includes/st_stm3220g_eval.mk
  210. +0 −1  support/make/build-rules.mk
  211. +0 −1  support/make/build-templates.mk
  212. +33 −64 support/make/target-config.mk
  213. +9 −13 wirish/{comm → }/HardwareSPI.cpp
  214. +134 −0 wirish/HardwareSerial.cpp
  215. +37 −28 wirish/HardwareTimer.cpp
  216. +3 −3 wirish/Print.cpp
  217. +108 −70 wirish/boards.cpp
  218. +20 −32 wirish/boards/{maple.cpp → VLDiscovery/board.cpp}
  219. +91 −0 wirish/boards/VLDiscovery/include/board/board.h
  220. +143 −0 wirish/boards/maple/board.cpp
  221. +17 −12 wirish/boards/{maple.h → maple/include/board/board.h}
  222. +5 −8 wirish/boards/{maple_RET6.cpp → maple_RET6/board.cpp}
  223. +5 −7 wirish/boards/{maple_RET6.h → maple_RET6/include/board/board.h}
  224. +6 −9 wirish/boards/{maple_mini.cpp → maple_mini/board.cpp}
  225. +4 −3 wirish/boards/{maple_mini.h → maple_mini/include/board/board.h}
  226. +7 −11 wirish/boards/{maple_native.cpp → maple_native/board.cpp}
  227. +4 −3 wirish/boards/{maple_native.h → maple_native/include/board/board.h}
  228. +6 −9 wirish/boards/{olimex_stm32_h103.cpp → olimex_stm32_h103/board.cpp}
  229. +2 −2 wirish/boards/{olimex_stm32_h103.h → olimex_stm32_h103/include/board/board.h}
  230. +60 −0 wirish/boards/st_stm3220g_eval/board.cpp
  231. +53 −0 wirish/boards/st_stm3220g_eval/include/board/board.h
  232. +71 −0 wirish/boards_private.h
  233. +0 −119 wirish/comm/HardwareSerial.cpp
  234. +9 −9 wirish/ext_interrupts.cpp
  235. +14 −7 wirish/{comm → include/wirish}/HardwareSPI.h
  236. +28 −12 wirish/{comm → include/wirish}/HardwareSerial.h
  237. +15 −9 wirish/{ → include/wirish}/HardwareTimer.h
  238. +3 −3 wirish/{ → include/wirish}/Print.h
  239. +6 −1 wirish/{ → include/wirish}/WProgram.h
  240. +2 −2 wirish/{ → include/wirish}/bit_constants.h
  241. +6 −1 wirish/{ → include/wirish}/bits.h
  242. +60 −42 wirish/{ → include/wirish}/boards.h
  243. +7 −8 wirish/{ → include/wirish}/ext_interrupts.h
  244. +8 −9 wirish/{ → include/wirish}/io.h
  245. +5 −6 wirish/{ → include/wirish}/pwm.h
  246. +7 −4 wirish/{ → include/wirish}/usb_serial.h
  247. +21 −17 wirish/{ → include/wirish}/wirish.h
  248. +6 −10 wirish/{ → include/wirish}/wirish_debug.h
  249. +4 −4 wirish/{ → include/wirish}/wirish_math.h
  250. +6 −6 wirish/{ → include/wirish}/wirish_time.h
  251. +7 −7 wirish/{ → include/wirish}/wirish_types.h
  252. +12 −9 wirish/pwm.cpp
  253. +33 −25 wirish/rules.mk
  254. +89 −0 wirish/stm32f1/boards_setup.cpp
  255. +83 −0 wirish/stm32f1/util_hooks.c
  256. +41 −0 wirish/stm32f1/wirish_debug.cpp
  257. +89 −0 wirish/stm32f1/wirish_digital.cpp
  258. +120 −0 wirish/stm32f2/boards_setup.cpp
  259. +45 −0 wirish/stm32f2/util_hooks.c
  260. +60 −0 wirish/stm32f2/wirish_debug.cpp
  261. +99 −0 wirish/stm32f2/wirish_digital.cpp
  262. +19 −16 {libmaple → wirish}/syscalls.c
  263. +15 −3 wirish/usb_serial.cpp
  264. +9 −8 wirish/wirish_analog.cpp
  265. +9 −61 wirish/wirish_digital.cpp
  266. +1 −1  wirish/wirish_math.cpp
  267. +29 −32 wirish/wirish_shift.cpp
  268. +3 −3 wirish/wirish_time.cpp
View
3  .gitignore
@@ -1,5 +1,6 @@
build/
-doxygen/
+doxygen/xml/
+doxygen/html/
main.cpp
libmaple.layout
tags
View
112 Makefile
@@ -19,10 +19,7 @@ SUPPORT_PATH := $(SRCROOT)/support
LDDIR := $(SUPPORT_PATH)/ld
# Support files for this Makefile
MAKEDIR := $(SUPPORT_PATH)/make
-
-# USB ID for DFU upload
-VENDOR_ID := 1EAF
-PRODUCT_ID := 0003
+BOARD_INCLUDE_DIR := $(MAKEDIR)/board-includes
##
## Target-specific configuration. This determines some compiler and
@@ -41,40 +38,42 @@ include $(MAKEDIR)/target-config.mk
## Compilation flags
##
-GLOBAL_FLAGS := -D$(VECT_BASE_ADDR) \
- -DBOARD_$(BOARD) -DMCU_$(MCU) \
- -DERROR_LED_PORT=$(ERROR_LED_PORT) \
- -DERROR_LED_PIN=$(ERROR_LED_PIN) \
- -D$(DENSITY)
+# FIXME: the following allows for deprecated include style, e.g.:
+# #include "libmaple.h"
+# or
+# #include "wirish.h"
+# It slows compilation noticeably; remove after 1 release.
+TARGET_FLAGS += -I$(LIBMAPLE_PATH)/include/libmaple \
+ -I$(WIRISH_PATH)/include/wirish
GLOBAL_CFLAGS := -Os -g3 -gdwarf-2 -mcpu=cortex-m3 -mthumb -march=armv7-m \
-nostdlib -ffunction-sections -fdata-sections \
- -Wl,--gc-sections $(GLOBAL_FLAGS)
-GLOBAL_CXXFLAGS := -fno-rtti -fno-exceptions -Wall $(GLOBAL_FLAGS)
+ -Wl,--gc-sections $(TARGET_FLAGS)
+GLOBAL_CXXFLAGS := -fno-rtti -fno-exceptions -Wall $(TARGET_FLAGS)
GLOBAL_ASFLAGS := -mcpu=cortex-m3 -march=armv7-m -mthumb \
- -x assembler-with-cpp $(GLOBAL_FLAGS)
-LDFLAGS = -T$(LDDIR)/$(LDSCRIPT) -L$(LDDIR) \
- -mcpu=cortex-m3 -mthumb -Xlinker -L $(LD_FAMILY_PATH) \
- -Xlinker --gc-sections -Xlinker --print-gc-sections \
- -Xassembler --march=armv7-m -Wall
+ -x assembler-with-cpp $(TARGET_FLAGS)
+LDFLAGS = $(TARGET_LDFLAGS) -mcpu=cortex-m3 -mthumb \
+ -Xlinker --gc-sections -Xlinker --print-gc-sections \
+ -Xassembler --march=armv7-m -Wall
##
## Build rules and useful templates
##
-include $(SUPPORT_PATH)/make/build-rules.mk
-include $(SUPPORT_PATH)/make/build-templates.mk
+include $(MAKEDIR)/build-rules.mk
+include $(MAKEDIR)/build-templates.mk
##
## Set all submodules here
##
LIBMAPLE_MODULES += $(SRCROOT)/libmaple
-LIBMAPLE_MODULES += $(LIBMAPLE_MODULE_FAMILY) # family submodule in libmaple
+LIBMAPLE_MODULES += $(SRCROOT)/libmaple/usb # The USB module is kept separate
+LIBMAPLE_MODULES += $(LIBMAPLE_MODULE_SERIES) # STM32 series submodule in libmaple
LIBMAPLE_MODULES += $(SRCROOT)/wirish
+
# Official libraries:
LIBMAPLE_MODULES += $(SRCROOT)/libraries/Servo
LIBMAPLE_MODULES += $(SRCROOT)/libraries/LiquidCrystal
LIBMAPLE_MODULES += $(SRCROOT)/libraries/Wire
-
# Experimental libraries:
LIBMAPLE_MODULES += $(SRCROOT)/libraries/FreeRTOS
@@ -93,16 +92,18 @@ $(foreach m,$(LIBMAPLE_MODULES),$(eval $(call LIBMAPLE_MODULE_template,$(m))))
# main target
include $(SRCROOT)/build-targets.mk
-.PHONY: install sketch clean help debug cscope tags ctags ram flash jtag doxygen mrproper
+.PHONY: install sketch clean help cscope tags ctags ram flash jtag doxygen mrproper list-boards
# Target upload commands
+# USB ID for DFU upload -- FIXME: do something smarter with this
+BOARD_USB_VENDOR_ID := 1EAF
+BOARD_USB_PRODUCT_ID := 0003
UPLOAD_ram := $(SUPPORT_PATH)/scripts/reset.py && \
sleep 1 && \
- $(DFU) -a0 -d $(VENDOR_ID):$(PRODUCT_ID) -D $(BUILD_PATH)/$(BOARD).bin -R
+ $(DFU) -a0 -d $(BOARD_USB_VENDOR_ID):$(BOARD_USB_PRODUCT_ID) -D $(BUILD_PATH)/$(BOARD).bin -R
UPLOAD_flash := $(SUPPORT_PATH)/scripts/reset.py && \
sleep 1 && \
- $(DFU) -a1 -d $(VENDOR_ID):$(PRODUCT_ID) -D $(BUILD_PATH)/$(BOARD).bin -R
-UPLOAD_jtag := $(OPENOCD_WRAPPER) flash
+ $(DFU) -a1 -d $(BOARD_USB_VENDOR_ID):$(BOARD_USB_PRODUCT_ID) -D $(BUILD_PATH)/$(BOARD).bin -R
# Conditionally upload to whatever the last build was
install: INSTALL_TARGET = $(shell cat $(BUILD_PATH)/build-type 2>/dev/null)
@@ -127,38 +128,37 @@ mrproper: clean
help:
@echo ""
- @echo " libmaple Makefile help"
- @echo " ----------------------"
- @echo " "
- @echo " Programming targets:"
- @echo " sketch: Compile for BOARD to MEMORY_TARGET (default)."
- @echo " install: Compile and upload code over USB, using Maple bootloader"
- @echo " "
- @echo " You *must* set BOARD if not compiling for Maple (e.g."
- @echo " use BOARD=maple_mini for mini, etc.), and MEMORY_TARGET"
- @echo " if not compiling to Flash."
- @echo " "
- @echo " Valid BOARDs:"
- @echo " maple, maple_mini, maple_RET6, maple_native"
- @echo " "
- @echo " Valid MEMORY_TARGETs (default=flash):"
- @echo " ram: Compile sketch code to ram"
- @echo " flash: Compile sketch code to flash"
- @echo " jtag: Compile sketch code for jtag; overwrites bootloader"
- @echo " "
- @echo " Other targets:"
- @echo " debug: Start OpenOCD gdb server on port 3333, telnet on port 4444"
- @echo " clean: Remove all build and object files"
- @echo " help: Show this message"
- @echo " doxygen: Build Doxygen HTML and XML documentation"
- @echo " mrproper: Remove all generated files"
- @echo " "
-
-debug:
- $(OPENOCD_WRAPPER) debug
+ @echo "Basic usage (BOARD defaults to maple):"
+ @echo " $$ cp your-main.cpp main.cpp"
+ @echo " $$ make BOARD=your_board"
+ @echo " $$ make BOARD=your_board install"
+ @echo ""
+ @echo "(Multiple source files? Link with libmaple.a (\`$$ make library')"
+ @echo "or hack build-targets.mk appropriately.)"
+ @echo ""
+ @echo "Important targets:"
+ @echo " sketch: Compile for BOARD to MEMORY_TARGET (default)."
+ @echo " install: Compile and upload over USB using Maple bootloader"
+ @echo ""
+ @echo "You *must* set BOARD if not compiling for Maple (e.g."
+ @echo "use BOARD=maple_mini for mini, etc.), and MEMORY_TARGET"
+ @echo "if not compiling to Flash. Run \`$$ make list-boards' for"
+ @echo "a list of all boards."
+ @echo ""
+ @echo "Valid MEMORY_TARGETs (default=flash):"
+ @echo " ram: Compile to RAM (doesn't touch Flash)"
+ @echo " flash: Compile to Flash (for Maple bootloader)"
+ @echo " jtag: Compile for JTAG/SWD upload (overwrites bootloader)"
+ @echo ""
+ @echo "Other targets:"
+ @echo " clean: Remove all build and object files"
+ @echo " doxygen: Build Doxygen HTML and XML documentation"
+ @echo " help: Show this message"
+ @echo " mrproper: Remove all generated files"
+ @echo ""
cscope:
- rm -rf *.cscope
+ rm -rf cscope.*
find . -name '*.[hcS]' -o -name '*.cpp' | xargs cscope -b
tags:
@@ -180,3 +180,7 @@ jtag:
doxygen:
doxygen $(SUPPORT_PATH)/doxygen/Doxyfile
+
+# This output is kind of ugly, but I don't understand make very well.
+list-boards:
+ @echo " $(addsuffix "\\n",$(basename $(notdir $(wildcard $(BOARD_INCLUDE_DIR)/*.mk))))"
View
1  README
@@ -122,7 +122,6 @@ Repository Layout
gdb/ GDB scripts.
ld/ Linker scripts.
make/ Additional scripts used by the top-level Makefile.
- openocd/ OpenOCD scripts for JTAG debugging.
scripts/ Miscellany.
doxygen/ Doxygen configuration.
stm32loader.py Script for uploading via the built-in USART bootloader.
View
0  support/openocd/debug_0.3.cfg → contrib/openocd/debug_0.3.cfg
File renamed without changes
View
0  support/openocd/debug_0.4.cfg → contrib/openocd/debug_0.4.cfg
File renamed without changes
View
0  support/openocd/flash_0.3.cfg → contrib/openocd/flash_0.3.cfg
File renamed without changes
View
0  support/openocd/flash_0.4.cfg → contrib/openocd/flash_0.4.cfg
File renamed without changes
View
0  support/scripts/openocd-wrapper.sh → contrib/openocd/openocd-wrapper.sh
File renamed without changes
View
2  examples/blinky.cpp
@@ -1,6 +1,6 @@
// Blinks the built-in LED
-#include "wirish.h"
+#include <wirish/wirish.h>
void setup() {
pinMode(BOARD_LED_PIN, OUTPUT);
View
12 examples/debug-dtrrts.cpp
@@ -1,7 +1,7 @@
// Test sketch for figuring out DTR/RTS behavior on different platforms.
-#include "wirish.h"
-#include "usb.h"
+#include <wirish/wirish.h>
+#include "usb_cdcacm.h"
void setup() {
/* Set up the LED to blink */
@@ -10,7 +10,6 @@ void setup() {
/* Send a message out USART2 */
Serial2.begin(9600);
Serial2.println("Debugging DTR/RTS...");
-
}
void loop() {
@@ -18,9 +17,9 @@ void loop() {
delay(100);
Serial2.print("DTR: ");
- Serial2.print(usbGetDTR(), DEC);
+ Serial2.print(usb_cdcacm_get_dtr(), DEC);
Serial2.print("\tRTS: ");
- Serial2.println(usbGetRTS(), DEC);
+ Serial2.println(usb_cdcacm_get_rts(), DEC);
}
// Force init to be called *first*, i.e. before static object allocation.
@@ -32,9 +31,8 @@ __attribute__((constructor)) void premain() {
int main(void) {
setup();
- while (1) {
+ while (true) {
loop();
}
return 0;
}
-
View
2  examples/freertos-blinky.cpp
@@ -1,4 +1,4 @@
-#include "wirish.h"
+#include <wirish/wirish.h>
#include "libraries/FreeRTOS/MapleFreeRTOS.h"
static void vLEDFlashTask(void *pvParameters) {
View
6 examples/fsmc-stress-test.cpp
@@ -12,9 +12,9 @@
#include <stdio.h>
#include <stddef.h>
-#include "wirish.h"
-#include "rcc.h"
-#include "fsmc.h"
+#include <wirish/wirish.h>
+#include <libmaple/rcc.h>
+#include <libmaple/fsmc.h>
// -- SRAM config -------------------------------------------------------------
View
145 examples/i2c-mcp4725-dac.cpp
@@ -0,0 +1,145 @@
+// i2c-mcp4725-dac.cpp
+//
+// Written by Andrew Meyer <ajm@leaflabs.com>
+// Modified by Marti Bolivar <mbolivar@leaflabs.com>
+//
+// Simple program showing how to control an MCP4725 DAC using the
+// libmaple I2C interface. There's an MCP4725 breakout board available
+// on SparkFun:
+//
+// http://www.sparkfun.com/products/8736
+//
+// How to use:
+//
+// 1. Connect the DAC SDA and SCL pins to I2C2, with a pullup
+// resistor (1 KOhm should work) to VCC.
+// 2. Load the sketch and connect to SerialUSB.
+// 3. Press the button.
+//
+// The program then makes sure the DAC is connected properly (during
+// setup()), then has the DAC output a sawtooth wave (with loop()).
+
+#include <wirish/wirish.h>
+#include <libmaple/i2c.h>
+
+#define MCP_ADDR 0x60
+#define MCP_WRITE_DAC 0b01000000
+#define MCP_WRITE_EEPROM 0b01100000
+#define MCP_PD_NORMAL 0b00000000
+#define MCP_PD_1K 0b00000010
+#define MCP_PD_100K 0b00000100
+#define MCP_PD_500K 0b00000110
+
+static uint8 write_msg_data[3];
+static i2c_msg write_msg;
+
+static uint8 read_msg_data[5];
+static i2c_msg read_msg;
+
+/*
+ * DAC control routines
+ */
+
+void mcp_i2c_setup(void) {
+ write_msg.addr = MCP_ADDR;
+ write_msg.flags = 0; // write, 7 bit address
+ write_msg.length = sizeof(write_msg_data);
+ write_msg.xferred = 0;
+ write_msg.data = write_msg_data;
+
+ read_msg.addr = MCP_ADDR;
+ read_msg.flags = I2C_MSG_READ;
+ read_msg.length = sizeof(read_msg_data);
+ read_msg.xferred = 0;
+ read_msg.data = read_msg_data;
+}
+
+void mcp_write_val(uint16 val) {
+ write_msg_data[0] = MCP_WRITE_DAC | MCP_PD_NORMAL;
+ uint16 tmp = val >> 4;
+ write_msg_data[1] = tmp;
+ tmp = (val << 4) & 0x00FF;
+ write_msg_data[2] = tmp;
+
+ i2c_master_xfer(I2C2, &write_msg, 1, 0);
+}
+
+uint16 mcp_read_val() {
+ uint16 tmp = 0;
+
+ i2c_master_xfer(I2C2, &read_msg, 1, 2);
+
+ /* We don't care about the status and EEPROM bytes (0, 3, and 4). */
+ tmp = (read_msg_data[1] << 4);
+ tmp += (read_msg_data[2] >> 4);
+ return tmp;
+}
+
+int mcp_test() {
+ uint16 val;
+ uint16 test_val = 0x0101;
+
+ SerialUSB.println("Testing the MCP4725...");
+ /* Read the value of the register (should be 0x0800 if factory fresh) */
+ val = mcp_read_val();
+ SerialUSB.print("DAC Register = 0x");
+ SerialUSB.println(val, HEX);
+
+ mcp_write_val(test_val);
+ SerialUSB.print("Wrote 0x");
+ SerialUSB.print(test_val, HEX);
+ SerialUSB.println(" to the DAC");
+
+ val = mcp_read_val();
+ SerialUSB.print("DAC Register = 0x");
+ SerialUSB.println(val, HEX);
+
+ if (val != test_val) {
+ SerialUSB.println("ERROR: MCP4725 not responding correctly");
+ return 0;
+ }
+
+ SerialUSB.println("MCP4725 seems to be working");
+ return 1;
+}
+
+/*
+ * setup() and loop()
+ */
+
+void setup() {
+ pinMode(BOARD_BUTTON_PIN, INPUT);
+ i2c_master_enable(I2C2, 0);
+ mcp_i2c_setup();
+
+ waitForButtonPress();
+ ASSERT(mcp_test());
+
+ SerialUSB.println("Starting sawtooth wave");
+}
+
+void loop() {
+ static uint16 dout = 0;
+
+ mcp_write_val(dout);
+
+ dout += 50;
+ if (dout >= 32768) {
+ dout = 0;
+ }
+}
+
+// -- init() and main() -------------------------------------------------------
+
+__attribute__((constructor)) void premain() {
+ init();
+}
+
+int main(void) {
+ setup();
+
+ while (true) {
+ loop();
+ }
+ return 0;
+}
View
2  examples/mini-exti-test.cpp
@@ -10,7 +10,7 @@
#include <stdio.h>
#include <string.h>
-#include "wirish.h"
+#include <wirish/wirish.h>
// test routines
void run_exti_test(void);
View
2  examples/qa-slave-shield.cpp
@@ -1,6 +1,6 @@
// Slave mode for Quality Assurance test
-#include "wirish.h"
+#include <wirish/wirish.h>
#define INTER_TOGGLE_DELAY_NORMAL 5
#define INTER_TOGGLE_DELAY_SLOW 80
View
30 examples/serial-echo.cpp
@@ -0,0 +1,30 @@
+// Simple serial port "echo". Send back any received data.
+
+#include <wirish/wirish.h>
+
+// Note: you can change "Serial1" to any other serial port you have on
+// your board.
+
+void setup() {
+ Serial1.begin(115200);
+}
+
+void loop() {
+ while (Serial1.available()) {
+ Serial1.write(Serial1.read());
+ }
+}
+
+// Force init() to be called before anything else.
+__attribute__((constructor)) void premain() {
+ init();
+}
+
+int main(void) {
+ setup();
+
+ while (true) {
+ loop();
+ }
+ return 0;
+}
View
2  examples/spi_master.cpp
@@ -33,7 +33,7 @@
* Pin 10 is used as slave select.
*/
-#include "wirish.h"
+#include <wirish/wirish.h>
#define NSS 10
View
6 examples/test-bkp.cpp
@@ -1,8 +1,8 @@
#include <stdio.h> // for snprintf()
-#include "wirish.h"
-#include "bkp.h"
-#include "iwdg.h"
+#include <wirish/wirish.h>
+#include <libmaple/bkp.h>
+#include <libmaple/iwdg.h>
void print_bkp_contents();
void write_to_bkp(uint16 val);
View
4 examples/test-dac.cpp
@@ -6,8 +6,8 @@
* This file is released into the public domain.
*/
-#include "wirish.h"
-#include "dac.h"
+#include <wirish/wirish.h>
+#include <libmaple/dac.h>
uint16 count = 0;
View
4 examples/test-fsmc.cpp
@@ -1,7 +1,7 @@
#include <stddef.h> // for ptrdiff_t
-#include "wirish.h"
-#include "fsmc.h"
+#include <wirish/wirish.h>
+#include <libmaple/fsmc.h>
#ifndef BOARD_maple_native
#error "Sorry, this example only works on Maple Native."
View
2  examples/test-print.cpp
@@ -8,7 +8,7 @@
* This file is released into the public domain.
*/
-#include "wirish.h"
+#include <wirish/wirish.h>
#undef min
#undef max
View
4 examples/test-ring-buffer-insertion.cpp
@@ -12,9 +12,9 @@
* This file is released into the public domain.
*/
-#include "wirish.h"
+#include <wirish/wirish.h>
-#include "ring_buffer.h"
+#include <libmaple/ring_buffer.h>
#define BUF_SIZE 64
ring_buffer ring_buf;
View
2  examples/test-serial-flush.cpp
@@ -2,7 +2,7 @@
* Tests the "flush" Serial function.
*/
-#include "wirish.h"
+#include <wirish/wirish.h>
void setup() {
Serial1.begin(9600);
View
6 examples/test-serialusb.cpp
@@ -1,7 +1,7 @@
// Tests SerialUSB functionality.
-#include "wirish.h"
-#include "usb.h"
+#include <wirish/wirish.h>
+#include "usb_cdcacm.h"
#define QUICKPRINT 0
#define BIGSTUFF 1
@@ -37,7 +37,7 @@ void loop() {
switch (state) {
case QUICKPRINT:
for (int i = 0; i < 30; i++) {
- usbSendBytes(&c1, 1);
+ usb_cdcacm_putc((char)c1, 1);
SerialUSB.print('.');
SerialUSB.print('|');
}
View
2  examples/test-servo.cpp
@@ -29,7 +29,7 @@
#include <stdio.h>
-#include "wirish.h"
+#include <wirish/wirish.h>
#include "libraries/Servo/Servo.h"
View
2  examples/test-session.cpp
@@ -4,7 +4,7 @@
// Useful for testing Maple features and troubleshooting.
// Communicates over SerialUSB.
-#include "wirish.h"
+#include <wirish/wirish.h>
// ASCII escape character
#define ESC ((uint8)27)
View
2  examples/test-spi-roundtrip.cpp
@@ -17,7 +17,7 @@
* Author: Marti Bolivar <mbolivar@leaflabs.com>
*/
-#include "wirish.h"
+#include <wirish/wirish.h>
HardwareSPI alice(2);
View
4 examples/test-systick.cpp
@@ -1,7 +1,7 @@
// Tests the SysTick enable/disable functions
-#include "wirish.h"
-#include "systick.h"
+#include <wirish/wirish.h>
+#include <libmaple/systick.h>
void setup() {
pinMode(BOARD_LED_PIN, OUTPUT);
View
710 examples/test-timers.cpp
@@ -1,288 +1,528 @@
-// Program to test the timer.h implementation's essential functionality.
-
-#include "wirish.h"
-#include "timer.h"
-
-void handler1(void);
-void handler2(void);
-void handler3(void);
-void handler4(void);
-
-void handler3b(void);
-void handler4b(void);
-
-int t;
-
-int count1 = 0;
-int count2 = 0;
-int count3 = 0;
-int count4 = 0;
-uint16 rate1 = 1000;
-uint16 rate2 = 2000;
-uint16 rate3 = 4000;
-uint16 rate4 = 8000;
-uint16 val1 = 10000;
-uint16 val2 = 10000;
-uint16 val3 = 10000;
-uint16 val4 = 10000;
-
-// FIXME [0.1.0] high density timer test (especially basic timers + DAC)
-timer_dev *timers[] = {TIMER1, TIMER2, TIMER3, TIMER4};
-voidFuncPtr handlers[] = {handler1, handler2, handler3, handler4};
-
-void initTimer(timer_dev *dev);
-void setTimerPeriod(timer_dev *dev, uint32 period_us);
-void testSetTimerPeriod(uint32 period);
-void testTimerChannels(timer_dev *dev);
-int timerNumber(timer_dev *dev);
+//
+// This is a mostly Wirish-free timer test. Wirish usage is minimized
+// because this is a test of the C timer interface in
+// <libmaple/timer.h>, so it's good if it can be made to work even
+// when most or all of Wirish is missing. Because of that, you may
+// need to customize the following output configuration:
+//
+// Output is printed:
+// - on COMM_USART,
+// - via TX pin on port COMM_USART_PORT, bit COMM_USART_TX_BIT
+// - via RX pin on port COMM_USART_PORT, bit COMM_USART_RX_BIT
+// - at COMM_USART_BAUD baud.
+#define COMM_USART USART6
+#define COMM_USART_BAUD 115200
+#define COMM_USART_PORT GPIOG
+#define COMM_USART_TX_BIT 14
+#define COMM_USART_RX_BIT 9
+// Other optional configuration below.
+
+#include <libmaple/libmaple.h>
+#include <libmaple/gpio.h>
+#include <libmaple/usart.h>
+#include <libmaple/systick.h>
+#include <libmaple/timer.h>
+#include <wirish/boards.h>
+
+//
+// Configuration
+//
+
+// More output if true
+static bool verbose = true;
+
+// Timers to test
+// FIXME use feature test macros for smaller MCUs
+static timer_dev *timers[] = {
+ // Available on all currently supported MCUs
+ TIMER1, TIMER2, TIMER3, TIMER4,
+ // Available on F1 (HD and up), F2
+ TIMER5, TIMER6, TIMER7, TIMER8,
+ // Available on F1 (XL), F2
+ TIMER9, TIMER10, TIMER11, TIMER12, TIMER13, TIMER14,
+};
+
+//
+// Test routines
+//
+
+typedef void (*timer_test_t)(timer_dev *);
+
+static void runTest(const char description[], timer_test_t test);
+static void runTests(void);
+
+static void testGetAndSetCount(timer_dev*);
+static void testPauseAndResume(timer_dev*);
+static void testTimerChannels(timer_dev*);
+
+//
+// Helpers
+//
+
+static void initTimer(timer_dev *dev);
+static int timerNumber(timer_dev *dev);
+// Hack: a systick-based delay, useful until delay_us() is fixed
+static void _delay(uint32 msec);
+// Wirish-less USART initialization routine
+static void init_usart(usart_dev *dev, gpio_dev *gdev, uint8 tx, uint8 rx);
+// Return whether or not the timer has capture/compare channel `ch'.
+// TODO: does something like this belong in the standard timer library?
+static bool timer_has_cc_ch(timer_dev *dev, int ch);
+
+// Printing routines and variants for verbose mode
+static void putstr(const char str[]);
+static void println(void);
+static void putstrln(const char str[]);
+static void putudec(uint32 val);
+static void puttimn(timer_dev *dev);
+static void v_putstr(const char str[]);
+static void v_println();
+static void v_putstrln(const char str[]);
+static void v_putudec(uint32 val);
+static void v_puttimn(timer_dev *dev);
+// Used to visually separate output from different tests
+static void printBanner(void);
+
+//
+// Handler state
+//
+
+static int count1 = 0;
+static int count2 = 0;
+static int count3 = 0;
+static int count4 = 0;
+static int timer_num; // Current timer we're considering
+
+//
+// Timer capture/compare interrupt handlers
+//
+// These are shared between timers. The global variable timer_num
+// controls which timer they affect.
+//
+
+static void handler1(void);
+static void handler2(void);
+static void handler3(void);
+static void handler4(void);
+static voidFuncPtr handlers[] = {handler1, handler2, handler3, handler4};
+
+//
+// setup() and loop()
+//
void setup() {
- // Set up the LED to blink
- pinMode(BOARD_LED_PIN, OUTPUT);
-
- // Setup the button as input
- pinMode(BOARD_BUTTON_PIN, INPUT);
-
- // Send a message out Serial2
- Serial2.begin(115200);
- Serial2.println("*** Initializing timers...");
+ init_usart(COMM_USART, COMM_USART_PORT,
+ COMM_USART_TX_BIT, COMM_USART_RX_BIT);
+ _delay(5);
+ println();
+ printBanner();
+ putstr("Initializing timers...\r\n");
timer_foreach(initTimer);
- Serial2.println("*** Done. Beginning timer test.");
+ putstr("Done. Running tests.\r\n");
+ runTests();
+ printBanner();
+ putstr("Done testing timers.\r\n");
}
void loop() {
- Serial2.println("-----------------------------------------------------");
-
- Serial2.println("Testing timer_get_count()/timer_set_count()");
- Serial2.print("TIMER1 count = ");
- Serial2.println(timer_get_count(TIMER1));
- Serial2.println("timer_set_count(TIMER1, 1234)");
- timer_set_count(TIMER1, 1234);
- Serial2.print("timer_get_count(TIMER1) = ");
- Serial2.println(timer_get_count(TIMER1));
-
- Serial2.println("-----------------------------------------------------");
- Serial2.println("Testing pause/resume; button roughly controls TIMER4");
- // when BUT is held down, TIMER4 is in the "pause" state and the
- // timer doesn't increment, so the final counts should reflect the
- // ratio of time that BUT was held down.
- count3 = 0;
- count4 = 0;
- timer_set_mode(TIMER3, TIMER_CH1, TIMER_OUTPUT_COMPARE);
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE);
- timer_pause(TIMER3);
- timer_pause(TIMER4);
- timer_set_count(TIMER3, 0);
- timer_set_count(TIMER4, 0);
- timer_set_reload(TIMER3, 30000);
- timer_set_reload(TIMER4, 30000);
- timer_set_compare(TIMER3, 1, 1000);
- timer_set_compare(TIMER4, 1, 1000);
- timer_attach_interrupt(TIMER3, TIMER_CC1_INTERRUPT, handler3b);
- timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler4b);
- timer_resume(TIMER3);
- timer_resume(TIMER4);
-
- Serial2.println("Testing for ~4 seconds...");
- for(int i = 0; i < 4000; i++) {
- if (isButtonPressed()) {
- timer_pause(TIMER4);
- } else {
- timer_resume(TIMER4);
- }
- delay(1);
- }
+}
- timer_set_mode(TIMER3, TIMER_CH1, TIMER_DISABLED);
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_DISABLED);
-
- Serial2.print("TIMER3 count: ");
- Serial2.println(timer_get_count(TIMER3));
- Serial2.print("TIMER4 count: ");
- Serial2.println(timer_get_count(TIMER4));
-
- Serial2.println("-----------------------------------------------------");
- Serial2.println("Testing setTimerPeriod()");
- testSetTimerPeriod(10);
- testSetTimerPeriod(30000);
- testSetTimerPeriod(300000);
- testSetTimerPeriod(30000);
-
- Serial2.println("Sanity check (with hand-coded reload and prescaler for "
- "72 MHz timers):");
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE);
- timer_set_prescaler(TIMER4, 33);
- timer_set_reload(TIMER4, 65454);
- timer_pause(TIMER4);
- timer_set_count(TIMER4, 0);
- timer_set_compare(TIMER4, TIMER_CH1, 1);
- timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler4b);
- Serial2.println("Period 30000ms, wait 2 seconds...");
- count4 = 0;
- timer_resume(TIMER4);
- delay(2000);
- timer_pause(TIMER4);
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_DISABLED);
- Serial2.print("TIMER4 count: ");
- Serial2.println(count4);
- Serial2.println(" (Should be around 2sec/30000ms ~ 67)");
-
- // Test all the individual timer channels
- timer_foreach(testTimerChannels);
+//
+// Test routine implementations
+//
+
+static void runTests(void) {
+ runTest("timer_get_count()/timer_set_count()", testGetAndSetCount);
+ runTest("timer_pause()/timer_resume()", testPauseAndResume);
+ runTest("capture/compare channels and interrupts",
+ testTimerChannels);
}
-void initTimer(timer_dev *dev) {
- switch (dev->type) {
- case TIMER_ADVANCED:
- case TIMER_GENERAL:
- Serial2.print("Initializing timer ");
- Serial2.println(timerNumber(dev));
- for (int c = 1; c <= 4; c++) {
- timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE);
- }
- Serial2.println("Done.");
- break;
- case TIMER_BASIC:
- break;
+static void runTest(const char description[], timer_test_t test) {
+ printBanner();
+ putstr("Testing ");
+ putstr(description);
+ putstrln(".");
+ timer_foreach(test);
+}
+
+static void testGetAndSetCount(timer_dev *dev) {
+ unsigned before, after;
+ unsigned val_to_set = 1234;
+
+ timer_pause(dev);
+ before = timer_get_count(dev);
+ timer_set_count(dev, val_to_set);
+ after = timer_get_count(dev);
+ timer_resume(dev);
+
+ if (after != val_to_set) {
+ puttimn(dev);
+ putstr(": ");
+ putstr("*** FAIL: get/set count for ");
+ puttimn(dev);
+ putstr(".");
+ putstr("Start count = ");
+ putudec(before);
+ putstr(". Count set to ");
+ putudec(val_to_set);
+ putstr(", and now count is = ");
+ putudec(after);
+ println();
+ } else if (verbose) {
+ puttimn(dev);
+ putstr(": ");
+ putstrln("[ok]");
}
}
-void testSetTimerPeriod(uint32 period) {
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE);
- timer_set_compare(TIMER4, TIMER_CH1, 1);
- setTimerPeriod(TIMER4, period);
- timer_pause(TIMER4);
- timer_set_count(TIMER4, 0);
- timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler4b);
- Serial2.println("Period ");
- Serial2.print(period);
- Serial2.print(" ms. Waiting 2 seconds...");
- count4 = 0;
- timer_resume(TIMER4);
- delay(2000);
- timer_pause(TIMER4);
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_DISABLED);
- Serial2.print("TIMER4 count: ");
- Serial2.println(timer_get_count(TIMER4));
- Serial2.print(" (Should be around 2 sec / ");
- Serial2.print(period);
- Serial2.print(" ms = ");
- Serial2.print(double(2) / period * 1000);
- Serial2.println(", modulo delays due to interrupts)");
+// This hack works on all currently supported STM32 series, but you
+// may need to do something smarter in the future. The assertions
+// ensure that our assumptions hold for your target.
+static timer_dev *getDifferentTimerOnSameBusAs(timer_dev *dev) {
+ rcc_clk_domain dev_domain = rcc_dev_clk(dev->clk_id);
+ ASSERT(RCC_APB1 == dev_domain || RCC_APB2 == dev_domain);
+ ASSERT(rcc_dev_clk(TIMER1->clk_id) == RCC_APB2);
+ ASSERT(rcc_dev_clk(TIMER2->clk_id) == RCC_APB1);
+ ASSERT(rcc_dev_clk(TIMER8->clk_id) == RCC_APB2);
+ ASSERT(rcc_dev_clk(TIMER3->clk_id) == RCC_APB1);
+
+ if (dev->clk_id == RCC_TIMER1) {
+ return TIMER8;
+ }
+ if (dev->clk_id == RCC_TIMER2) {
+ return TIMER3;
+ }
+ return dev_domain == RCC_APB2 ? TIMER1 : TIMER2;
}
-int timerNumber(timer_dev *dev) {
- switch (dev->clk_id) {
- case RCC_TIMER1:
- return 1;
- case RCC_TIMER2:
- return 2;
- case RCC_TIMER3:
- return 3;
- case RCC_TIMER4:
- return 4;
-#ifdef STM32_HIGH_DENSITY
- case RCC_TIMER5:
- return 5;
- case RCC_TIMER6:
- return 6;
- case RCC_TIMER7:
- return 7;
- case RCC_TIMER8:
- return 8;
-#endif
- default:
- ASSERT(0);
- return 0;
+// Rough test of pause and resume.
+//
+// Approximately half the time, dev is in the "pause" state and the
+// timer doesn't increment, while another timer (`base_dev') on the
+// same bus continues. dev and base_dev have identical start counts
+// and prescalers.
+//
+// Since dev and base_dev share a bus (and thus a base clock), and we
+// configure them to have the same prescaler and start count, the
+// ratio of their end counts should be approximately 1 : 2. We check
+// to make sure this is true, up to tolerance `epsilon'.
+static void testPauseAndResume(timer_dev *dev) {
+ timer_dev *base_dev = getDifferentTimerOnSameBusAs(dev);
+ unsigned start_count = 0, reload = 65535;
+ // This prescaler should be enough to ensure that we don't
+ // overflow, while still giving us a reasonably large number of
+ // timer ticks.
+ uint16 prescaler = CYCLES_PER_MICROSECOND * 50;
+ double epsilon = .02;
+
+ if (rcc_dev_clk(base_dev->clk_id) != rcc_dev_clk(dev->clk_id)) {
+ putstrln("*** ERROR: cannot run test. Bus info is messed up.");
+ return;
+ }
+
+ // Pause and set up timers
+ timer_pause(base_dev);
+ timer_pause(dev);
+ timer_set_count(base_dev, start_count);
+ timer_set_count(dev, start_count);
+ timer_set_reload(base_dev, reload);
+ timer_set_reload(dev, reload);
+ timer_set_prescaler(base_dev, prescaler);
+ timer_set_prescaler(dev, prescaler);
+ timer_generate_update(base_dev);
+ timer_generate_update(dev);
+
+ // Resume the timers and run the test
+ ASSERT(timer_get_count(base_dev) == start_count);
+ ASSERT(timer_get_count(dev) == start_count);
+ timer_resume(base_dev);
+ timer_resume(dev);
+ _delay(1000);
+ timer_pause(dev);
+ _delay(1000);
+ timer_pause(base_dev);
+
+ // Check the results
+ unsigned dev_count = timer_get_count(dev);
+ unsigned base_count = timer_get_count(base_dev);
+ double count_ratio = ((double)dev_count / base_count);
+ bool fail = false;
+ if (count_ratio > 0.5 + epsilon || count_ratio < 0.5 - epsilon) {
+ fail = true;
+ }
+ if (fail || verbose) {
+ puttimn(dev);
+ putstr(" vs. ");
+ puttimn(base_dev);
+ putstr(": ");
+ if (fail) putstr("*** FAIL: ");
+ else putstr("[ok] ");
+ putstr("(dev = ");
+ putudec(dev_count);
+ putstr(") / (base = ");
+ putudec(base_count);
+ putstr(") = ");
+ // hack hack hack
+ putudec((int)count_ratio);
+ count_ratio -= (int)count_ratio;
+ putstr(".");
+ int cr_x_100 = (int)(count_ratio * 100);
+ int hundredths = cr_x_100 % 10;
+ cr_x_100 /= 10;
+ int tenths = cr_x_100 % 10;
+ putudec(tenths);
+ putudec(hundredths);
+ println();
}
}
-/* This function touches every channel of a given timer. The output
- * ratios should reflect the ratios of the rate variables. It
- * demonstrates that, over time, the actual timing rates get blown
- * away by other system interrupts. */
-void testTimerChannels(timer_dev *dev) {
- t = timerNumber(dev);
- toggleLED();
- delay(100);
- Serial2.println("-----------------------------------------------------");
+// This function touches every capture/compare channel of a given
+// timer. The channel counts should be equal within a timer
+// regardless of other interrupts on the system (note that this
+// doesn't really test timers with only a single capture/compare
+// channel; for that, you'll want to do visual inspection of timers
+// that share a bus, in verbose mode).
+static void testTimerChannels(timer_dev *dev) {
switch (dev->type) {
case TIMER_BASIC:
- Serial2.print("NOT testing channels for basic timer ");
- Serial2.println(t);
- break;
+ v_putstr("Skipping basic timer ");
+ v_puttimn(dev);
+ v_println();
+ return;
case TIMER_ADVANCED:
case TIMER_GENERAL:
- Serial2.print("Testing channels for timer ");
- Serial2.println(t);
+ // Set up
+ v_puttimn(dev);
+ v_println();
+ v_putstr("\tchannels: ");
+
+ timer_num = timerNumber(dev);
timer_pause(dev);
- count1 = count2 = count3 = count4 = 0;
+ count1 = 0;
+ count2 = 0;
+ count3 = 0;
+ count4 = 0;
timer_set_reload(dev, 0xFFFF);
timer_set_prescaler(dev, 1);
for (int c = 1; c <= 4; c++) {
- timer_set_compare(dev, c, 65535);
- timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE);
- timer_attach_interrupt(dev, c, handlers[c - 1]);
+ if (timer_has_cc_ch(dev, c)) {
+ v_putudec(c);
+ v_putstr("\t");
+ timer_set_compare(dev, c, 0xFFFF);
+ timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE);
+ timer_attach_interrupt(dev, c, handlers[c - 1]);
+ }
}
+ v_println();
+
+ // Run test
+ timer_generate_update(dev);
timer_resume(dev);
- delay(3000);
+ _delay(250);
+ timer_pause(dev);
+
+ // Print results
+ v_putstr("\tcounts: ");
+ bool fail = false;
+ bool mismatched[4] = {false, false, false, false};
+ int counts[4];
+ counts[0] = count1;
+ counts[1] = count2;
+ counts[2] = count3;
+ counts[3] = count4;
+ bool first = true;
+ int first_count = -1;
+ for (int c = 1; c <= 4; c++) {
+ if (timer_has_cc_ch(dev, c)) {
+ if (first) {
+ first_count = counts[c - 1];
+ first = false;
+ }
+ if (!first && (counts[c - 1] != first_count)) {
+ mismatched[c - 1] = true;
+ fail = true;
+ }
+ v_putudec(counts[c - 1]);
+ v_putstr("\t");
+ }
+ }
+ v_println();
+ if (fail) {
+ for (int i = 0; i < 4; i++) {
+ if (mismatched[i]) {
+ putstr("*** FAIL: mismatch on ");
+ puttimn(dev);
+ putstr(", channel ");
+ putudec(i + 1);
+ putstr(": expected ");
+ putudec(first_count);
+ putstr(", got ");
+ putudec(counts[i]);
+ println();
+ }
+ }
+ } else {
+ puttimn(dev);
+ putstrln(" [ok]");
+ }
+ v_println();
+
+ // Clean up
for (int c = 1; c <= 4; c++) {
- timer_set_mode(dev, c, TIMER_DISABLED);
+ if (timer_has_cc_ch(dev, c)) {
+ timer_set_mode(dev, c, TIMER_DISABLED);
+ }
}
- Serial2.print("Channel 1 count: "); Serial2.println(count1);
- Serial2.print("Channel 2 count: "); Serial2.println(count2);
- Serial2.print("Channel 3 count: "); Serial2.println(count3);
- Serial2.print("Channel 4 count: "); Serial2.println(count4);
break;
}
}
-// FIXME [0.1.0] move some incarnation of this into timer.h
-void setTimerPeriod(timer_dev *dev, uint32 period_us) {
- if (!period_us) {
- // FIXME handle this case
- ASSERT(0);
- return;
- }
+//
+// Helper implementations
+//
- uint32 cycles = period_us * CYCLES_PER_MICROSECOND;
- uint16 pre = (uint16)((cycles >> 16) + 1);
- timer_set_prescaler(dev, pre);
- timer_set_reload(dev, cycles / pre - 1);
+static void _delay(uint32 msec) {
+ uint32 end = systick_uptime() + msec;
+ while (systick_uptime() < end)
+ ;
}
-void handler1(void) {
- val1 += rate1;
- timer_set_compare(timers[t], TIMER_CH1, val1);
- count1++;
+static void init_usart(usart_dev *dev, gpio_dev *gdev, uint8 tx, uint8 rx) {
+ usart_config_gpios_async(dev, gdev, rx, gdev, tx, 0);
+ usart_init(dev);
+ usart_set_baud_rate(dev, USART_USE_PCLK, COMM_USART_BAUD);
+ usart_enable(dev);
}
-void handler2(void) {
- val2 += rate2;
- timer_set_compare(timers[t], TIMER_CH2, val2);
- count2++;
+static bool timer_has_cc_ch(timer_dev *dev, int ch) {
+ ASSERT(1 <= ch && ch <= 4);
+ if (dev->type == TIMER_BASIC)
+ return false;
+ int tn = timerNumber(dev);
+ return (// TIM1-5 and 8 have all four channels
+ (tn <= 5 || tn == 8) ||
+ // TIM9 and 12 only have channels 1 and 2
+ ((tn == 9 || tn == 12) && ch <= 2) ||
+ // All other general purpose timers only have channel 1
+ (ch == 1));
}
-void handler3(void) {
- val3 += rate3;
- timer_set_compare(timers[t], TIMER_CH3, val3);
- count3++;
+static void putstr(const char str[]) {
+ usart_putstr(COMM_USART, str);
}
-void handler4(void) {
- val4 += rate4;
- timer_set_compare(timers[t], TIMER_CH4, val4);
- count4++;
+static void println(void) {
+ putstr("\r\n");
}
-void handler3b(void) {
+static void putstrln(const char str[]) {
+ putstr(str);
+ println();
+}
+
+static void putudec(uint32 val) {
+ usart_putudec(COMM_USART, val);
+}
+
+static void puttimn(timer_dev *dev) {
+ putstr("TIM");
+ putudec(timerNumber(dev));
+}
+
+static void v_putstr(const char str[]) {
+ if (verbose) putstr(str);
+}
+
+static void v_println() {
+ if (verbose) println();
+}
+
+__attribute__((unused)) /* (shut up, gcc) */
+static void v_putstrln(const char str[]) {
+ if (verbose) putstrln(str);
+}
+
+static void v_putudec(uint32 val) {
+ if (verbose) putudec(val);
+}
+
+static void v_puttimn(timer_dev *dev) {
+ if (verbose) puttimn(dev);
+}
+
+// Used to visually separate output from different tests
+static void printBanner(void) {
+ putstrln("-----------------------------------------------------");
+}
+
+static void initTimer(timer_dev *dev) {
+ v_puttimn(dev);
+ timer_init(dev);
+ switch (dev->type) {
+ case TIMER_ADVANCED:
+ case TIMER_GENERAL:
+ v_putstr(" channels ");
+ for (int c = 1; c <= 4; c++) {
+ if (timer_has_cc_ch(dev, c)) {
+ v_putudec(c);
+ v_putstr(" ");
+ timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE);
+ }
+ }
+ break;
+ case TIMER_BASIC:
+ break;
+ }
+ v_println();
+}
+
+static int timerNumber(timer_dev *dev) {
+ switch (dev->clk_id) {
+ case RCC_TIMER1: return 1;
+ case RCC_TIMER2: return 2;
+ case RCC_TIMER3: return 3;
+ case RCC_TIMER4: return 4;
+ case RCC_TIMER5: return 5;
+ case RCC_TIMER6: return 6;
+ case RCC_TIMER7: return 7;
+ case RCC_TIMER8: return 8;
+ case RCC_TIMER9: return 9;
+ case RCC_TIMER10: return 10;
+ case RCC_TIMER11: return 11;
+ case RCC_TIMER12: return 12;
+ case RCC_TIMER13: return 13;
+ case RCC_TIMER14: return 14;
+ default:
+ ASSERT(0);
+ return 0;
+ }
+}
+
+//
+// IRQ Handlers
+//
+
+static void handler1(void) {
+ count1++;
+}
+
+static void handler2(void) {
+ count2++;
+}
+
+static void handler3(void) {
count3++;
}
-void handler4b(void) {
+static void handler4(void) {
count4++;
}
+//
+// init() and main()
+//
+
__attribute__((constructor)) void premain() {
init();
}
View
220 examples/test-usart-dma.cpp
@@ -1,5 +1,5 @@
/**
- * @file test-usart-dma.cpp
+ * @file examples/test-usart-dma.cpp
* @author Marti Bolivar <mbolivar@leaflabs.com>
*
* Simple test of DMA used with a USART receiver.
@@ -12,100 +12,188 @@
*
* This example isn't very robust; don't use it in production. In
* particular, since the buffer keeps filling (DMA_CIRC_MODE is set),
- * if you keep typing after filling the buffer, you'll overwrite
- * earlier bytes; this may happen before those earlier bytes are done
- * printing.
+ * if you keep sending characters after filling the buffer, you'll
+ * overwrite earlier bytes; this may happen before those earlier bytes
+ * are done printing. (Typing quickly and seeing how it affects the
+ * output is a fun way to make sense of how the interrupts and the
+ * main thread of execution interleave.)
*
* This code is released into the public domain.
*/
-#include "dma.h"
-#include "usart.h"
-#include "gpio.h"
+#include <libmaple/dma.h>
+#include <libmaple/usart.h>
+#include <libmaple/gpio.h>
-#include "wirish.h"
+#include <wirish/wirish.h>
-#define BAUD 9600
+/*
+ * Configuration and state
+ */
-#define USART USART2
-#define USART_HWSER Serial2
+// Serial port and DMA configuration. You can change these to suit
+// your purposes.
+HardwareSerial *serial = &Serial2;
#define USART_DMA_DEV DMA1
-#define USART_RX_DMA_CHANNEL DMA_CH6
-#define USART_TX BOARD_USART2_TX_PIN
-#define USART_RX BOARD_USART2_RX_PIN
+#if STM32_MCU_SERIES == STM32_SERIES_F1
+// On STM32F1 microcontrollers (like what's on Maple and Maple Mini),
+// dma tubes are channels.
+#define USART_RX_DMA_TUBE DMA_CH6
+#elif (STM32_MCU_SERIES == STM32_SERIES_F2 || \
+ STM32_MCU_SERIES == STM32_SERIES_F4)
+// On STM32F2 and STM32F4 microcontrollers (Maple 2 will have an F4),
+// dma tubes are streams.
+#define USART_RX_DMA_TUBE DMA_S5
+#else
+#error "unsupported stm32 series"
+#endif
+// The serial port will make a DMA request each time it receives data.
+// This is the dma_request_src we use to tell the DMA tube to handle
+// that DMA request.
+#define USART_DMA_REQ_SRC DMA_REQ_SRC_USART2_RX
+#define BAUD 9600
-#define BUF_SIZE 8
-uint8 rx_buf[BUF_SIZE];
+// This will store the DMA configuration for USART RX.
+dma_tube_config tube_config;
-dma_irq_cause irq_cause;
+// This will store received USART characters.
+#define BUF_SIZE 20
+char rx_buf[BUF_SIZE];
+// The interrupt handler, rx_dma_irq(), sets this to 1.
volatile uint32 irq_fired = 0;
+// Used to store DMA interrupt status register (ISR) bits inside
+// rx_dma_irq(). This helps explain what's going on inside loop(); see
+// comments below.
+volatile uint32 isr = 0;
+
+/*
+ * Helper functions
+ */
+
+// This is our DMA interrupt handler.
+void rx_dma_irq(void) {
+ irq_fired = 1;
+ isr = dma_get_isr_bits(USART_DMA_DEV, USART_RX_DMA_TUBE);
+}
+
+// Configure the USART receiver for use with DMA:
+// 1. Turn it on.
+// 2. Set the "DMA request on RX" bit in USART_CR3 (USART_CR3_DMAR).
+void setup_usart(void) {
+ serial->begin(BAUD);
+ usart_dev *serial_dev = serial->c_dev();
+ serial_dev->regs->CR3 = USART_CR3_DMAR;
+}
+
+// Set up our dma_tube_config structure. (We could have done this
+// above, when we declared tube_config, but having this function makes
+// it easier to explain what's going on).
+void setup_tube_config(void) {
+ // We're receiving from the USART data register. serial->c_dev()
+ // returns a pointer to the libmaple usart_dev for that serial
+ // port, so this is a pointer to its data register.
+ tube_config.tube_src = &serial->c_dev()->regs->DR;
+ // We're only interested in the bottom 8 bits of that data register.
+ tube_config.tube_src_size = DMA_SIZE_8BITS;
+ // We're storing to rx_buf.
+ tube_config.tube_dst = rx_buf;
+ // rx_buf is a char array, and a "char" takes up 8 bits on STM32.
+ tube_config.tube_dst_size = DMA_SIZE_8BITS;
+ // Only fill BUF_SIZE - 1 characters, to leave a null byte at the end.
+ tube_config.tube_nr_xfers = BUF_SIZE - 1;
+ // Flags:
+ // - DMA_CFG_DST_INC so we start at the beginning of rx_buf and
+ // fill towards the end.
+ // - DMA_CFG_CIRC so we go back to the beginning and start over when
+ // rx_buf fills up.
+ // - DMA_CFG_CMPLT_IE to turn on interrupts on transfer completion.
+ tube_config.tube_flags = DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
+ // Target data: none. It's important to set this to NULL if you
+ // don't have any special (microcontroller-specific) configuration
+ // in mind, which we don't.
+ tube_config.target_data = NULL;
+ // DMA request source.
+ tube_config.tube_req_src = USART_DMA_REQ_SRC;
+}
+
+// Configure the DMA controller to serve DMA requests from the USART.
+void setup_dma_xfer(void) {
+ // First, turn it on.
+ dma_init(USART_DMA_DEV);
+ // Next, configure it by calling dma_tube_cfg(), and check to make
+ // sure it succeeded. DMA tubes have many restrictions on their
+ // configuration, and there are configurations which work on some
+ // types of STM32 but not others. libmaple tries hard to make
+ // things just work, but checking the return status is important!
+ int status = dma_tube_cfg(USART_DMA_DEV, USART_RX_DMA_TUBE, &tube_config);
+ ASSERT(status == DMA_TUBE_CFG_SUCCESS);
+ // Now we'll perform any other configuration we want. For this
+ // example, we attach an interrupt handler.
+ dma_attach_interrupt(USART_DMA_DEV, USART_RX_DMA_TUBE, rx_dma_irq);
+ // Turn on the DMA tube. It will now begin serving requests.
+ dma_enable(USART_DMA_DEV, USART_RX_DMA_TUBE);
+}
-void init_usart(void);
-void init_dma_xfer(void);
-void rx_dma_irq(void);
+/*
+ * setup() and loop()
+ */
void setup(void) {
pinMode(BOARD_LED_PIN, OUTPUT);
-
- init_dma_xfer();
- init_usart();
+ setup_tube_config();
+ setup_dma_xfer();
+ setup_usart();
}
void loop(void) {
toggleLED();
delay(100);
- dma_channel_reg_map *ch_regs = dma_channel_regs(USART_DMA_DEV,
- USART_RX_DMA_CHANNEL);
+ // See if the interrupt handler got called since the last time we
+ // checked.
if (irq_fired) {
- USART_HWSER.println("** IRQ **");
+ serial->println("** IRQ **");
+ // Notice how the interrupt status register (ISR) bits show
+ // transfer complete _and_ half-complete here, but the ISR
+ // bits we print next will be zero. That's because the
+ // variable "isr" gets set _inside_ rx_dma_irq(). After it
+ // exits, libmaple cleans up by clearing the tube's ISR
+ // bits. (If it didn't, and we forgot to, the interrupt would
+ // repeatedly fire forever.)
+ serial->print("ISR bits: 0x");
+ serial->println(isr, HEX);
irq_fired = 0;
}
- USART_HWSER.print("[");
- USART_HWSER.print(millis());
- USART_HWSER.print("]\tISR bits: 0x");
- uint8 isr_bits = dma_get_isr_bits(USART_DMA_DEV, USART_RX_DMA_CHANNEL);
- USART_HWSER.print(isr_bits, HEX);
- USART_HWSER.print("\tCCR: 0x");
- USART_HWSER.print(ch_regs->CCR, HEX);
- USART_HWSER.print("\tCNDTR: 0x");
- USART_HWSER.print(ch_regs->CNDTR, HEX);
- USART_HWSER.print("\tBuffer contents: ");
- for (int i = 0; i < BUF_SIZE; i++) {
- USART_HWSER.print('\'');
- USART_HWSER.print(rx_buf[i]);
- USART_HWSER.print('\'');
- if (i < BUF_SIZE - 1) USART_HWSER.print(", ");
- }
- USART_HWSER.println();
+
+ // Print the ISR bits.
+ //
+ // Notice that the "transfer half-complete" ISR flag gets set when
+ // we reach the rx_buf half-way point. This is true even though we
+ // don't tell the DMA controller to interrupt us on a
+ // half-complete transfer. That is, the ISR bits get set at the
+ // right times no matter what; we just don't get interrupted
+ // unless we asked. (If an error or other problem occurs, the
+ // relevant ISR bits will get set in the same way).
+ serial->print("[");
+ serial->print(millis());
+ serial->print("]\tISR bits: 0x");
+ uint8 isr_bits = dma_get_isr_bits(USART_DMA_DEV, USART_RX_DMA_TUBE);
+ serial->print(isr_bits, HEX);
+
+ // Print the contents of rx_buf. If you keep typing after it fills
+ // up, the new characters will overwrite the old ones, thanks to
+ // DMA_CIRC_MODE.
+ serial->print("\tCharacter buffer contents: '");
+ serial->print(rx_buf);
+ serial->println("'");
if (isr_bits == 0x7) {
- USART_HWSER.println("** Clearing ISR bits.");
- dma_clear_isr_bits(USART_DMA_DEV, USART_RX_DMA_CHANNEL);
+ serial->println("** Clearing ISR bits.");
+ dma_clear_isr_bits(USART_DMA_DEV, USART_RX_DMA_TUBE);
}
}
-/* Configure USART receiver for use with DMA */
-void init_usart(void) {
- USART_HWSER.begin(BAUD);
- USART->regs->CR3 = USART_CR3_DMAR;
-}
-
-/* Configure DMA transmission */
-void init_dma_xfer(void) {
- dma_init(USART_DMA_DEV);
- dma_setup_transfer(USART_DMA_DEV, USART_RX_DMA_CHANNEL,
- &USART->regs->DR, DMA_SIZE_8BITS,
- rx_buf, DMA_SIZE_8BITS,
- (DMA_MINC_MODE | DMA_CIRC_MODE | DMA_TRNS_CMPLT));
- dma_set_num_transfers(USART_DMA_DEV, USART_RX_DMA_CHANNEL, BUF_SIZE);
- dma_attach_interrupt(USART_DMA_DEV, USART_RX_DMA_CHANNEL, rx_dma_irq);
- dma_enable(USART_DMA_DEV, USART_RX_DMA_CHANNEL);
-}
-
-void rx_dma_irq(void) {
- irq_fired = true;
-}
+// ------- init() and main() --------------------------------------------------
// Force init to be called *first*, i.e. before static object allocation.
// Otherwise, statically allocated objects that need libmaple may fail.
View
2  examples/vga-leaf.cpp
@@ -32,7 +32,7 @@
// FIXME: generalize for Native and Mini
-#include "wirish.h"
+#include <wirish/wirish.h>
// Pinouts -- you also must change the GPIO macros below if you change
// these
View
4 examples/vga-scope.cpp
@@ -35,8 +35,8 @@
Marti Bolivar <mbolivar@leaflabs.com>
*/
-#include "wirish.h"
-#include "systick.h"
+#include <wirish/wirish.h>
+#include <libmaple/systick.h>
// FIXME: generalize for Native and Mini
View
78 libmaple/adc.c
@@ -25,44 +25,15 @@
*****************************************************************************/
/**
- * @file adc.c
- *
+ * @file libmaple/adc.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>,
+ * Perry Hung <perry@leaflabs.com>
* @brief Analog to digital converter routines
- *
- * IMPORTANT: maximum external impedance must be below 0.4kOhms for 1.5
- * sample conversion time.
- *
- * At 55.5 cycles/sample, the external input impedance < 50kOhms.
- *
- * See STM32 manual RM0008 for how to calculate this.
*/
-#include "libmaple.h"
-#include "rcc.h"
-#include "adc.h"
-
-static adc_dev adc1 = {
- .regs = ADC1_BASE,
- .clk_id = RCC_ADC1
-};
-/** ADC1 device. */
-const adc_dev *ADC1 = &adc1;
-
-static adc_dev adc2 = {
- .regs = ADC2_BASE,
- .clk_id = RCC_ADC2
-};
-/** ADC2 device. */
-const adc_dev *ADC2 = &adc2;
-
-#ifdef STM32_HIGH_DENSITY
-adc_dev adc3 = {
- .regs = ADC3_BASE,
- .clk_id = RCC_ADC3
-};
-/** ADC3 device. */
-const adc_dev *ADC3 = &adc3;
-#endif
+#include <libmaple/adc.h>
+#include <libmaple/libmaple.h>
+#include <libmaple/rcc.h>
/**
* @brief Initialize an ADC peripheral.
@@ -91,20 +62,10 @@ void adc_set_extsel(const adc_dev *dev, adc_extsel_event event) {
}
/**
- * @brief Call a function on all ADC devices.
- * @param fn Function to call on each ADC device.
- */
-void adc_foreach(void (*fn)(const adc_dev*)) {
- fn(ADC1);
- fn(ADC2);
-#ifdef STM32_HIGH_DENSITY
- fn(ADC3);
-#endif
-}
-
-/**
- * @brief Turn the given sample rate into values for ADC_SMPRx. Don't
- * call this during conversion.
+ * @brief Set the sample rate for all channels on an ADC device.
+ *
+ * Don't call this during conversion.
+ *
* @param dev adc device
* @param smp_rate sample rate to set
* @see adc_smp_rate
@@ -127,25 +88,8 @@ void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate) {
}
/**
- * @brief Calibrate an ADC peripheral
- * @param dev adc device
- */
-void adc_calibrate(const adc_dev *dev) {
- __io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3);
- __io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2);
-
- *rstcal_bit = 1;
- while (*rstcal_bit)
- ;
-
- *cal_bit = 1;
- while (*cal_bit)
- ;
-}
-
-/**
* @brief Perform a single synchronous software triggered conversion on a
- * channel.
+ * channel.
* @param dev ADC device to use for reading.
* @param channel channel to convert
* @return conversion result
View
28 libmaple/dac.c
@@ -2,6 +2,7 @@
* The MIT License
*
* Copyright (c) 2010 Bryan Newbold.
+ * Copyright (c) 2011, 2012 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -25,25 +26,20 @@
*****************************************************************************/
/**
- * @file dac.c
+ * @file libmaple/dac.c
* @brief Digital to analog converter support.
*/
-#include "libmaple.h"
-#include "gp