From 662d2af1624e378e67665e1db4ea28d17abc18ed Mon Sep 17 00:00:00 2001 From: Michael Dryden Date: Sat, 29 Sep 2012 02:48:35 -0400 Subject: [PATCH] New source rewrite --- .gitignore | 29 + DSTAT-temp/DSTAT-temp.cproj | 607 +++++++ DSTAT-temp/atmel_devices_cdc.inf | 140 ++ DSTAT-temp/src/ads1255.c | 493 +++++ DSTAT-temp/src/ads1255.h | 82 + DSTAT-temp/src/asf.h | 120 ++ DSTAT-temp/src/asf/common/boards/board.h | 291 +++ .../src/asf/common/boards/user_board/init.c | 18 + .../asf/common/boards/user_board/user_board.h | 37 + .../src/asf/common/services/clock/genclk.h | 176 ++ .../src/asf/common/services/clock/osc.h | 162 ++ .../src/asf/common/services/clock/pll.h | 318 ++++ .../src/asf/common/services/clock/sysclk.h | 169 ++ .../src/asf/common/services/clock/xmega/osc.h | 461 +++++ .../src/asf/common/services/clock/xmega/pll.h | 262 +++ .../asf/common/services/clock/xmega/sysclk.c | 244 +++ .../asf/common/services/clock/xmega/sysclk.h | 1393 ++++++++++++++ .../src/asf/common/services/delay/delay.h | 137 ++ .../services/delay/xmega/cycle_counter.h | 113 ++ .../src/asf/common/services/ioport/ioport.h | 515 ++++++ .../asf/common/services/ioport/xmega/ioport.h | 337 ++++ .../services/ioport/xmega/ioport_compat.c | 70 + .../services/ioport/xmega/ioport_compat.h | 315 ++++ .../asf/common/services/sleepmgr/sleepmgr.h | 241 +++ .../common/services/sleepmgr/xmega/sleepmgr.c | 58 + .../common/services/sleepmgr/xmega/sleepmgr.h | 114 ++ .../src/asf/common/services/spi/usart_spi.h | 99 + .../services/spi/xmega_usart_spi/usart_spi.c | 137 ++ .../services/spi/xmega_usart_spi/usart_spi.h | 239 +++ .../services/usb/class/cdc/device/udi_cdc.c | 1037 +++++++++++ .../services/usb/class/cdc/device/udi_cdc.h | 764 ++++++++ .../usb/class/cdc/device/udi_cdc_conf.h | 145 ++ .../usb/class/cdc/device/udi_cdc_desc.c | 225 +++ .../services/usb/class/cdc/usb_protocol_cdc.h | 315 ++++ .../src/asf/common/services/usb/udc/udc.c | 1090 +++++++++++ .../src/asf/common/services/usb/udc/udc.h | 726 ++++++++ .../asf/common/services/usb/udc/udc_desc.h | 131 ++ .../src/asf/common/services/usb/udc/udd.h | 392 ++++ .../src/asf/common/services/usb/udc/udi.h | 130 ++ .../src/asf/common/services/usb/usb_atmel.h | 185 ++ .../asf/common/services/usb/usb_protocol.h | 410 +++++ DSTAT-temp/src/asf/common/utils/interrupt.h | 139 ++ .../common/utils/interrupt/interrupt_avr8.h | 138 ++ .../src/asf/common/utils/make/Makefile.avr.in | 455 +++++ DSTAT-temp/src/asf/common/utils/parts.h | 671 +++++++ DSTAT-temp/src/asf/common/utils/stdio/read.c | 164 ++ .../common/utils/stdio/stdio_usb/stdio_usb.c | 133 ++ .../common/utils/stdio/stdio_usb/stdio_usb.h | 128 ++ DSTAT-temp/src/asf/common/utils/stdio/write.c | 146 ++ DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.h | 120 ++ DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.s | 100 + .../asf/xmega/drivers/cpu/xmega_reset_cause.h | 105 ++ DSTAT-temp/src/asf/xmega/drivers/nvm/nvm.c | 757 ++++++++ DSTAT-temp/src/asf/xmega/drivers/nvm/nvm.h | 1057 +++++++++++ .../src/asf/xmega/drivers/nvm/nvm_asm.s | 197 ++ DSTAT-temp/src/asf/xmega/drivers/pmic/pmic.h | 349 ++++ DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.c | 240 +++ DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.h | 290 +++ .../src/asf/xmega/drivers/sleep/sleep.h | 166 ++ DSTAT-temp/src/asf/xmega/drivers/tc/tc.c | 1078 +++++++++++ DSTAT-temp/src/asf/xmega/drivers/tc/tc.h | 1612 +++++++++++++++++ .../src/asf/xmega/drivers/usart/usart.c | 491 +++++ .../src/asf/xmega/drivers/usart/usart.h | 555 ++++++ .../src/asf/xmega/drivers/usb/usb_device.c | 1448 +++++++++++++++ .../src/asf/xmega/drivers/usb/usb_device.h | 387 ++++ DSTAT-temp/src/asf/xmega/utils/assembler.h | 156 ++ .../src/asf/xmega/utils/assembler/gas.h | 121 ++ .../asf/xmega/utils/bit_handling/clz_ctz.h | 212 +++ DSTAT-temp/src/asf/xmega/utils/compiler.h | 1039 +++++++++++ .../asf/xmega/utils/preprocessor/mrepeat.h | 335 ++++ .../xmega/utils/preprocessor/preprocessor.h | 51 + .../asf/xmega/utils/preprocessor/stringz.h | 81 + .../src/asf/xmega/utils/preprocessor/tpaste.h | 101 ++ DSTAT-temp/src/asf/xmega/utils/progmem.h | 99 + DSTAT-temp/src/asf/xmega/utils/status_codes.h | 115 ++ DSTAT-temp/src/config/conf_board.h | 11 + DSTAT-temp/src/config/conf_clock.h | 98 + DSTAT-temp/src/config/conf_rtc.h | 50 + DSTAT-temp/src/config/conf_sleepmgr.h | 49 + DSTAT-temp/src/config/conf_usart_spi.h | 47 + DSTAT-temp/src/config/conf_usb.h | 165 ++ DSTAT-temp/src/main.c | 76 + DSTAT-temp/src/main.h | 54 + DSTAT-temp/src/main1.c | 1375 ++++++++++++++ DSTAT-temp/src/max5443.c | 89 + DSTAT-temp/src/max5443.h | 18 + DSTAT1.atsln | 14 +- DSTAT1.atsuo | Bin 0 -> 34304 bytes DSTAT1/DSTAT1.cproj | 254 +-- .../services/hugemem/avr8/avr8_hugemem.c | 195 ++ .../common/services/hugemem/avr8/hugemem.h | 163 ++ .../common/services/hugemem/generic/hugemem.h | 112 ++ .../src/asf/common/services/hugemem/hugemem.h | 140 ++ .../src/asf/common/services/ioport/ioport.h | 515 ++++++ .../asf/common/services/ioport/xmega/ioport.h | 337 ++++ .../services/ioport/xmega/ioport_compat.c | 70 + .../services/ioport/xmega/ioport_compat.h | 315 ++++ DSTAT1/src/asf/common/utils/parts.h | 671 +++++++ DSTAT1/src/asf/xmega/drivers/dma/dma.c | 280 +++ DSTAT1/src/asf/xmega/drivers/dma/dma.h | 1394 ++++++++++++++ DSTAT1/src/main.h | 4 - 101 files changed, 32524 insertions(+), 135 deletions(-) create mode 100644 .gitignore create mode 100644 DSTAT-temp/DSTAT-temp.cproj create mode 100644 DSTAT-temp/atmel_devices_cdc.inf create mode 100644 DSTAT-temp/src/ads1255.c create mode 100644 DSTAT-temp/src/ads1255.h create mode 100644 DSTAT-temp/src/asf.h create mode 100644 DSTAT-temp/src/asf/common/boards/board.h create mode 100644 DSTAT-temp/src/asf/common/boards/user_board/init.c create mode 100644 DSTAT-temp/src/asf/common/boards/user_board/user_board.h create mode 100644 DSTAT-temp/src/asf/common/services/clock/genclk.h create mode 100644 DSTAT-temp/src/asf/common/services/clock/osc.h create mode 100644 DSTAT-temp/src/asf/common/services/clock/pll.h create mode 100644 DSTAT-temp/src/asf/common/services/clock/sysclk.h create mode 100644 DSTAT-temp/src/asf/common/services/clock/xmega/osc.h create mode 100644 DSTAT-temp/src/asf/common/services/clock/xmega/pll.h create mode 100644 DSTAT-temp/src/asf/common/services/clock/xmega/sysclk.c create mode 100644 DSTAT-temp/src/asf/common/services/clock/xmega/sysclk.h create mode 100644 DSTAT-temp/src/asf/common/services/delay/delay.h create mode 100644 DSTAT-temp/src/asf/common/services/delay/xmega/cycle_counter.h create mode 100644 DSTAT-temp/src/asf/common/services/ioport/ioport.h create mode 100644 DSTAT-temp/src/asf/common/services/ioport/xmega/ioport.h create mode 100644 DSTAT-temp/src/asf/common/services/ioport/xmega/ioport_compat.c create mode 100644 DSTAT-temp/src/asf/common/services/ioport/xmega/ioport_compat.h create mode 100644 DSTAT-temp/src/asf/common/services/sleepmgr/sleepmgr.h create mode 100644 DSTAT-temp/src/asf/common/services/sleepmgr/xmega/sleepmgr.c create mode 100644 DSTAT-temp/src/asf/common/services/sleepmgr/xmega/sleepmgr.h create mode 100644 DSTAT-temp/src/asf/common/services/spi/usart_spi.h create mode 100644 DSTAT-temp/src/asf/common/services/spi/xmega_usart_spi/usart_spi.c create mode 100644 DSTAT-temp/src/asf/common/services/spi/xmega_usart_spi/usart_spi.h create mode 100644 DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc.c create mode 100644 DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc.h create mode 100644 DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc_conf.h create mode 100644 DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc_desc.c create mode 100644 DSTAT-temp/src/asf/common/services/usb/class/cdc/usb_protocol_cdc.h create mode 100644 DSTAT-temp/src/asf/common/services/usb/udc/udc.c create mode 100644 DSTAT-temp/src/asf/common/services/usb/udc/udc.h create mode 100644 DSTAT-temp/src/asf/common/services/usb/udc/udc_desc.h create mode 100644 DSTAT-temp/src/asf/common/services/usb/udc/udd.h create mode 100644 DSTAT-temp/src/asf/common/services/usb/udc/udi.h create mode 100644 DSTAT-temp/src/asf/common/services/usb/usb_atmel.h create mode 100644 DSTAT-temp/src/asf/common/services/usb/usb_protocol.h create mode 100644 DSTAT-temp/src/asf/common/utils/interrupt.h create mode 100644 DSTAT-temp/src/asf/common/utils/interrupt/interrupt_avr8.h create mode 100644 DSTAT-temp/src/asf/common/utils/make/Makefile.avr.in create mode 100644 DSTAT-temp/src/asf/common/utils/parts.h create mode 100644 DSTAT-temp/src/asf/common/utils/stdio/read.c create mode 100644 DSTAT-temp/src/asf/common/utils/stdio/stdio_usb/stdio_usb.c create mode 100644 DSTAT-temp/src/asf/common/utils/stdio/stdio_usb/stdio_usb.h create mode 100644 DSTAT-temp/src/asf/common/utils/stdio/write.c create mode 100644 DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.h create mode 100644 DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.s create mode 100644 DSTAT-temp/src/asf/xmega/drivers/cpu/xmega_reset_cause.h create mode 100644 DSTAT-temp/src/asf/xmega/drivers/nvm/nvm.c create mode 100644 DSTAT-temp/src/asf/xmega/drivers/nvm/nvm.h create mode 100644 DSTAT-temp/src/asf/xmega/drivers/nvm/nvm_asm.s create mode 100644 DSTAT-temp/src/asf/xmega/drivers/pmic/pmic.h create mode 100644 DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.c create mode 100644 DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.h create mode 100644 DSTAT-temp/src/asf/xmega/drivers/sleep/sleep.h create mode 100644 DSTAT-temp/src/asf/xmega/drivers/tc/tc.c create mode 100644 DSTAT-temp/src/asf/xmega/drivers/tc/tc.h create mode 100644 DSTAT-temp/src/asf/xmega/drivers/usart/usart.c create mode 100644 DSTAT-temp/src/asf/xmega/drivers/usart/usart.h create mode 100644 DSTAT-temp/src/asf/xmega/drivers/usb/usb_device.c create mode 100644 DSTAT-temp/src/asf/xmega/drivers/usb/usb_device.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/assembler.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/assembler/gas.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/bit_handling/clz_ctz.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/compiler.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/preprocessor/mrepeat.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/preprocessor/preprocessor.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/preprocessor/stringz.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/preprocessor/tpaste.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/progmem.h create mode 100644 DSTAT-temp/src/asf/xmega/utils/status_codes.h create mode 100644 DSTAT-temp/src/config/conf_board.h create mode 100644 DSTAT-temp/src/config/conf_clock.h create mode 100644 DSTAT-temp/src/config/conf_rtc.h create mode 100644 DSTAT-temp/src/config/conf_sleepmgr.h create mode 100644 DSTAT-temp/src/config/conf_usart_spi.h create mode 100644 DSTAT-temp/src/config/conf_usb.h create mode 100644 DSTAT-temp/src/main.c create mode 100644 DSTAT-temp/src/main.h create mode 100644 DSTAT-temp/src/main1.c create mode 100644 DSTAT-temp/src/max5443.c create mode 100644 DSTAT-temp/src/max5443.h create mode 100644 DSTAT1.atsuo create mode 100644 DSTAT1/src/asf/common/services/hugemem/avr8/avr8_hugemem.c create mode 100644 DSTAT1/src/asf/common/services/hugemem/avr8/hugemem.h create mode 100644 DSTAT1/src/asf/common/services/hugemem/generic/hugemem.h create mode 100644 DSTAT1/src/asf/common/services/hugemem/hugemem.h create mode 100644 DSTAT1/src/asf/common/services/ioport/ioport.h create mode 100644 DSTAT1/src/asf/common/services/ioport/xmega/ioport.h create mode 100644 DSTAT1/src/asf/common/services/ioport/xmega/ioport_compat.c create mode 100644 DSTAT1/src/asf/common/services/ioport/xmega/ioport_compat.h create mode 100644 DSTAT1/src/asf/common/utils/parts.h create mode 100644 DSTAT1/src/asf/xmega/drivers/dma/dma.c create mode 100644 DSTAT1/src/asf/xmega/drivers/dma/dma.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bc8230 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ + +#ignore thumbnails created by windows +Thumbs.db +#Ignore files build by Visual Studio +*.obj +*.exe +*.pdb +*.user +*.aps +*.pch +*.vspscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.cache +*.ilk +*.log +[Bb]in +[Dd]ebug*/ +*.lib +*.sbr +obj/ +[Rr]elease*/ +_ReSharper*/ +[Tt]est[Rr]esult* diff --git a/DSTAT-temp/DSTAT-temp.cproj b/DSTAT-temp/DSTAT-temp.cproj new file mode 100644 index 0000000..f608949 --- /dev/null +++ b/DSTAT-temp/DSTAT-temp.cproj @@ -0,0 +1,607 @@ + + + + 2.0 + 6.0 + {511f3fe1-f6b0-4e6d-877c-322c1167607e} + $(MSBuildProjectName) + $(MSBuildProjectName) + $(MSBuildProjectName) + 3.4.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ATxmega256A3U + xmegaau + C + com.Atmel.AVRGCC8 + + $(MSBuildProjectDirectory)\$(Configuration) + $(MSBuildProjectName) + .elf + Executable + Native + true + false + + 0 + + + + + True + True + True + + + BOARD=USER_BOARD + IOPORT_XMEGA_COMPAT + + + + + ../src + ../src/asf/common/applications/user_application/user_board + ../src/asf/common/boards + ../src/asf/common/boards/user_board + ../src/asf/common/utils + ../src/asf/xmega/utils + ../src/asf/xmega/utils/preprocessor + ../src/config + ../src/asf/xmega/drivers/cpu + ../src/asf/xmega/drivers/nvm + ../src/asf/xmega/drivers/pmic + ../src/asf/xmega/drivers/rtc + ../src/asf/xmega/drivers/sleep + ../src/asf/xmega/drivers/tc + ../src/asf/xmega/drivers/usart + ../src/asf/common/services/clock + ../src/asf/common/services/delay + ../src/asf/common/services/ioport + ../src/asf/common/services/sleepmgr + ../src/asf/common/services/spi + ../src/asf/common/services/usb + ../src/asf/common/services/usb/class/cdc + ../src/asf/common/services/usb/class/cdc/device + ../src/asf/common/services/usb/udc + ../src/asf/common/utils/stdio/stdio_usb + ../src/asf/xmega/drivers/usb + + + Optimize for size (-Os) + -fdata-sections + True + True + -Werror-implicit-function-declaration -Wmissing-prototypes -Wpointer-arith -Wstrict-prototypes -mrelax -std=gnu99 + + + + True + True + -Wl,--relax + -DBOARD=USER_BOARD -mrelax + + + ../src + ../src/asf/common/applications/user_application/user_board + ../src/asf/common/boards + ../src/asf/common/boards/user_board + ../src/asf/common/utils + ../src/asf/xmega/utils + ../src/asf/xmega/utils/preprocessor + ../src/config + ../src/asf/xmega/drivers/cpu + ../src/asf/xmega/drivers/nvm + ../src/asf/xmega/drivers/pmic + ../src/asf/xmega/drivers/rtc + ../src/asf/xmega/drivers/sleep + ../src/asf/xmega/drivers/tc + ../src/asf/xmega/drivers/usart + ../src/asf/common/services/clock + ../src/asf/common/services/delay + ../src/asf/common/services/ioport + ../src/asf/common/services/sleepmgr + ../src/asf/common/services/spi + ../src/asf/common/services/usb + ../src/asf/common/services/usb/class/cdc + ../src/asf/common/services/usb/class/cdc/device + ../src/asf/common/services/usb/udc + ../src/asf/common/utils/stdio/stdio_usb + ../src/asf/xmega/drivers/usb + + + + + + True + True + True + True + + + + + True + True + True + + + BOARD=USER_BOARD + IOPORT_XMEGA_COMPAT + + + + + ../src + ../src/asf/common/applications/user_application/user_board + ../src/asf/common/boards + ../src/asf/common/boards/user_board + ../src/asf/common/utils + ../src/asf/xmega/utils + ../src/asf/xmega/utils/preprocessor + ../src/config + ../src/asf/xmega/drivers/cpu + ../src/asf/xmega/drivers/nvm + ../src/asf/xmega/drivers/pmic + ../src/asf/xmega/drivers/rtc + ../src/asf/xmega/drivers/sleep + ../src/asf/xmega/drivers/tc + ../src/asf/xmega/drivers/usart + ../src/asf/common/services/clock + ../src/asf/common/services/delay + ../src/asf/common/services/ioport + ../src/asf/common/services/sleepmgr + ../src/asf/common/services/spi + ../src/asf/common/services/usb + ../src/asf/common/services/usb/class/cdc + ../src/asf/common/services/usb/class/cdc/device + ../src/asf/common/services/usb/udc + ../src/asf/common/utils/stdio/stdio_usb + ../src/asf/xmega/drivers/usb + + + Optimize (-O1) + -fdata-sections + True + Maximum (-g3) + True + -Werror-implicit-function-declaration -Wmissing-prototypes -Wpointer-arith -Wstrict-prototypes -mrelax -std=gnu99 + + + + True + True + -Wl,--relax + -DBOARD=USER_BOARD -mrelax + + + ../src + ../src/asf/common/applications/user_application/user_board + ../src/asf/common/boards + ../src/asf/common/boards/user_board + ../src/asf/common/utils + ../src/asf/xmega/utils + ../src/asf/xmega/utils/preprocessor + ../src/config + ../src/asf/xmega/drivers/cpu + ../src/asf/xmega/drivers/nvm + ../src/asf/xmega/drivers/pmic + ../src/asf/xmega/drivers/rtc + ../src/asf/xmega/drivers/sleep + ../src/asf/xmega/drivers/tc + ../src/asf/xmega/drivers/usart + ../src/asf/common/services/clock + ../src/asf/common/services/delay + ../src/asf/common/services/ioport + ../src/asf/common/services/sleepmgr + ../src/asf/common/services/spi + ../src/asf/common/services/usb + ../src/asf/common/services/usb/class/cdc + ../src/asf/common/services/usb/class/cdc/device + ../src/asf/common/services/usb/udc + ../src/asf/common/utils/stdio/stdio_usb + ../src/asf/xmega/drivers/usb + + + + + + True + True + True + True + + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DSTAT-temp/atmel_devices_cdc.inf b/DSTAT-temp/atmel_devices_cdc.inf new file mode 100644 index 0000000..af75045 --- /dev/null +++ b/DSTAT-temp/atmel_devices_cdc.inf @@ -0,0 +1,140 @@ +; Windows 2000, XP, Vista and 7 (x32 and x64) setup file for Atmel CDC Devices + +; Copyright (c) 2000 Microsoft Corporation +; Copyright (C) 2000-2012 ATMEL, Inc. + +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} + +Provider=%ATMEL% +LayoutFile=layout.inf +DriverVer=10/15/1999,5.0.2153.1 + +;---------------------------------------------------------- +; Targets +;---------------------------------------------------------- +[Manufacturer] +%ATMEL%=ATMEL, NTamd64 + +[ATMEL] +%ATMEL_CDC_XPLAINED%=Reader, USB\VID_03EB&PID_2122 +%ATMEL_CDC_SFW_EXAMPLE%=Reader, USB\VID_03EB&PID_2307 +%ATMEL_CDC_EVK1XXX%=Reader, USB\VID_03EB&PID_2310 +%ATMEL_CDC_ASF_EXAMPLE%=Reader, USB\VID_03EB&PID_2404 +%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE2%=Reader, USB\VID_03EB&PID_2421&MI_00 +%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE4%=Reader, USB\VID_03EB&PID_2424&MI_00 +%ATMEL_CDC_ASF_EXAMPLE2_COM1%=Reader, USB\VID_03EB&PID_2425&MI_00 +%ATMEL_CDC_ASF_EXAMPLE2_COM2%=Reader, USB\VID_03EB&PID_2425&MI_02 +%ATMEL_CDC_ASF_EXAMPLE3_COM1%=Reader, USB\VID_03EB&PID_2426&MI_00 +%ATMEL_CDC_ASF_EXAMPLE3_COM2%=Reader, USB\VID_03EB&PID_2426&MI_02 +%ATMEL_CDC_ASF_EXAMPLE3_COM3%=Reader, USB\VID_03EB&PID_2426&MI_04 +%ATMEL_CDC_ASF_EXAMPLE3_COM4%=Reader, USB\VID_03EB&PID_2426&MI_06 +%ATMEL_CDC_ASF_EXAMPLE3_COM5%=Reader, USB\VID_03EB&PID_2426&MI_08 +%ATMEL_CDC_ASF_EXAMPLE3_COM6%=Reader, USB\VID_03EB&PID_2426&MI_0A +%ATMEL_CDC_ASF_EXAMPLE3_COM7%=Reader, USB\VID_03EB&PID_2426&MI_0C + +[ATMEL.NTamd64] +%ATMEL_CDC_XPLAINED%=DriverInstall, USB\VID_03EB&PID_2122 +%ATMEL_CDC_SFW_EXAMPLE%=DriverInstall, USB\VID_03EB&PID_2307 +%ATMEL_CDC_EVK1XXX%=DriverInstall, USB\VID_03EB&PID_2310 +%ATMEL_CDC_ASF_EXAMPLE%=DriverInstall, USB\VID_03EB&PID_2404 +%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE2%=DriverInstall, USB\VID_03EB&PID_2421&MI_00 +%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE4%=DriverInstall, USB\VID_03EB&PID_2424&MI_00 +%ATMEL_CDC_ASF_EXAMPLE2_COM1%=DriverInstall, USB\VID_03EB&PID_2425&MI_00 +%ATMEL_CDC_ASF_EXAMPLE2_COM2%=DriverInstall, USB\VID_03EB&PID_2425&MI_02 +%ATMEL_CDC_ASF_EXAMPLE3_COM1%=DriverInstall, USB\VID_03EB&PID_2426&MI_00 +%ATMEL_CDC_ASF_EXAMPLE3_COM2%=DriverInstall, USB\VID_03EB&PID_2426&MI_02 +%ATMEL_CDC_ASF_EXAMPLE3_COM3%=DriverInstall, USB\VID_03EB&PID_2426&MI_04 +%ATMEL_CDC_ASF_EXAMPLE3_COM4%=DriverInstall, USB\VID_03EB&PID_2426&MI_06 +%ATMEL_CDC_ASF_EXAMPLE3_COM5%=DriverInstall, USB\VID_03EB&PID_2426&MI_08 +%ATMEL_CDC_ASF_EXAMPLE3_COM6%=DriverInstall, USB\VID_03EB&PID_2426&MI_0A +%ATMEL_CDC_ASF_EXAMPLE3_COM7%=DriverInstall, USB\VID_03EB&PID_2426&MI_0C + +;---------------------------------------------------------- +; Windows 2K, XP, and Vista32 +;---------------------------------------------------------- +[Reader_Install.NTx86] + + +[DestinationDirs] +DefaultDestDir=12 +Reader.NT.Copy=12 + +[Reader.NT] +include=mdmcpq.inf +CopyFiles=Reader.NT.Copy +AddReg=Reader.NT.AddReg + +[Reader.NT.Copy] +usbser.sys + +[Reader.NT.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[Reader.NT.Services] +AddService = usbser, 0x00000002, Service_Inst + +[Service_Inst] +DisplayName = %Serial.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\usbser.sys +LoadOrderGroup = Base + + +;---------------------------------------------------------- +; Vista64 +;---------------------------------------------------------- + +[DriverInstall.NTamd64] +include=mdmcpq.inf +CopyFiles=DriverCopyFiles.NTamd64 +AddReg=DriverInstall.NTamd64.AddReg + +[DriverCopyFiles.NTamd64] +usbser.sys,,,0x20 + +[DriverInstall.NTamd64.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.NTamd64.Services] +AddService=usbser, 0x00000002, DriverService.NTamd64 + +[DriverService.NTamd64] +DisplayName=%Serial.SvcDesc% +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\usbser.sys + +;---------------------------------------------------------- +; String +;---------------------------------------------------------- + +[Strings] +ATMEL = "ATMEL, Inc." +ATMEL_CDC_XPLAINED = "XPLAINED Virtual Com Port" +ATMEL_CDC_SFW_EXAMPLE = "Communication Device Class SFW example" +ATMEL_CDC_EVK1XXX = "EVK1XXX Virtual Com Port" +ATMEL_CDC_ASF_EXAMPLE = "Communication Device Class ASF example" +ATMEL_CDC_ASF_COMPOSITE_EXAMPLE2 = "Communication Device Class ASF composite example 2" +ATMEL_CDC_ASF_COMPOSITE_EXAMPLE4 = "Communication Device Class ASF composite example 4" +ATMEL_CDC_ASF_EXAMPLE2_COM1 = "Communication Device Class ASF example2, COM1" +ATMEL_CDC_ASF_EXAMPLE2_COM2 = "Communication Device Class ASF example2, COM2" +ATMEL_CDC_ASF_EXAMPLE3_COM1 = "Communication Device Class ASF example3, COM1" +ATMEL_CDC_ASF_EXAMPLE3_COM2 = "Communication Device Class ASF example3, COM2" +ATMEL_CDC_ASF_EXAMPLE3_COM3 = "Communication Device Class ASF example3, COM3" +ATMEL_CDC_ASF_EXAMPLE3_COM4 = "Communication Device Class ASF example3, COM4" +ATMEL_CDC_ASF_EXAMPLE3_COM5 = "Communication Device Class ASF example3, COM5" +ATMEL_CDC_ASF_EXAMPLE3_COM6 = "Communication Device Class ASF example3, COM6" +ATMEL_CDC_ASF_EXAMPLE3_COM7 = "Communication Device Class ASF example3, COM7" + +Serial.SvcDesc = "USB Serial emulation driver" + diff --git a/DSTAT-temp/src/ads1255.c b/DSTAT-temp/src/ads1255.c new file mode 100644 index 0000000..8a4dffb --- /dev/null +++ b/DSTAT-temp/src/ads1255.c @@ -0,0 +1,493 @@ +/* + * ads1255.c + * + * Created: 04/04/2012 2:13:47 PM + * Author: mdryden + */ + + +#include +//#include + +uint8_t buffer_iter = 0; + +struct usart_spi_device spi_device_conf = { + .id = IOPORT_CREATE_PIN(PORTE, 4) + }; + +// struct spi_device spi_device_conf = { +// .id = IOPORT_CREATE_PIN(PORTE, 4) +// }; + + +void ads1255_init_pins(void) + { + ioport_configure_port_pin(&PORTE, PIN4_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTE, PIN6_bm, IOPORT_DIR_INPUT); + ioport_configure_port_pin(&PORTE, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + //DRDY +// ioport_configure_port_pin(&PORTE, PIN3_bm, IOPORT_DIR_INPUT | IOPORT_FALLING); v1 Board + ioport_configure_port_pin(&PORTD, PIN5_bm, IOPORT_DIR_INPUT | IOPORT_FALLING); + } + + + void ads1255_init_module(void) + { +// spi_master_init(&SPIE); +// spi_master_setup_device(&SPIE, &spi_device_conf, SPI_MODE_1, 2300000UL, 0); +// spi_enable(&SPIE); + + usart_spi_init(&USARTE1); + usart_spi_setup_device(&USARTE1, &spi_device_conf, SPI_MODE_1, 2300000UL, 0); +// USARTE1.BAUDCTRLB = 0; +// USARTE1.BAUDCTRLA = 0b10; +// delay_s(1); + +// usart_spi_enable(&USARTE1); + } + +void ads1255_sync(void){ +// uint8_t ctrlbuffer = ADS_SYNC; + +// spi_select_device(&SPIE, &spi_device_conf); +// spi_write_packet(&SPIE, &ctrlbuffer, 1); +// spi_deselect_device(&SPIE, &spi_device_conf); + + usart_spi_select_device(&USARTE1, &spi_device_conf); + usart_spi_transmit(&USARTE1, ADS_SYNC); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + + return; +} + + +int32_t ads1255_single_read(void){ + + union{ + uint8_t uint[4]; + int32_t int32; + } input_buffer; + +// spi_select_device(&SPIE, &spi_device_conf); +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// spi_write_single(&SPIE, ADS_RDATA); +// delay_us(6.5); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[2] = spi_get(&SPIE); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[1] = spi_get(&SPIE); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[0] = spi_get(&SPIE); +// spi_write_single(&SPIE, ADS_STANDBY); +// +// spi_deselect_device(&SPIE, &spi_device_conf); + + usart_spi_select_device(&USARTE1, &spi_device_conf); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + usart_spi_transmit(&USARTE1, ADS_RDATA); + delay_us(6.5); + for (int i = 2; i >= 0; --i) + { + while (usart_data_register_is_empty(&USARTE1) == false); + usart_put(&USARTE1, CONFIG_USART_SPI_DUMMY); + while (usart_rx_is_complete(&USARTE1) == false); + input_buffer.uint[i] = usart_get(&USARTE1); + } + while (!usart_tx_is_complete(&USARTE1)); + usart_clear_tx_complete(&USARTE1); + + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + + + ads1255_standby(); + + if (input_buffer.uint[2] > 0x7F) + input_buffer.uint[3] = 0xFF; + else + input_buffer.uint[3] = 0x0; + + #ifdef ADS1255_DBG + printf(logstr1, "ADS1255 result=%li\n\r",input_buffer.int32); + #endif + + if (input_buffer.int32 > ADS_OVERCURRENT_THRESHOLD || (-1*input_buffer.int32) > (ADS_OVERCURRENT_THRESHOLD)) + { + over_under[buffer_iter] = 1; + if (buffer_iter == (ADS_OVER_UNDER_SAMPLES - 1)) + buffer_iter = 0; + else + buffer_iter++; + } + else if (input_buffer.int32 < ADS_UNDERCURRENT_THRESHOLD && (input_buffer.int32*-1) < (ADS_UNDERCURRENT_THRESHOLD)) + { + over_under[buffer_iter] = -1; + if (buffer_iter == (ADS_OVER_UNDER_SAMPLES - 1)) + buffer_iter = 0; + else + buffer_iter++; + } + else + { + over_under[buffer_iter] = 0; + if (buffer_iter == (ADS_OVER_UNDER_SAMPLES - 1)) + buffer_iter = 0; + else + buffer_iter++; + } + + return input_buffer.int32; +} +int16_t ads1255_read_fast(void){ + + + union{ + uint8_t uint[2]; + int16_t int16; + } input_buffer; + +// spi_select_device(&SPIE, &spi_device_conf); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[1] = spi_get(&SPIE); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[0] = spi_get(&SPIE); +// spi_deselect_device(&SPIE, &spi_device_conf); + + + usart_spi_select_device(&USARTE1, &spi_device_conf); + + for (int i = 1; i >= 0; --i){ + while (usart_data_register_is_empty(&USARTE1) == false); + usart_put(&USARTE1, CONFIG_USART_SPI_DUMMY); + while (usart_rx_is_complete(&USARTE1) == false); + input_buffer.uint[i] = usart_get(&USARTE1); + } + while (!usart_tx_is_complete(&USARTE1)); + usart_clear_tx_complete(&USARTE1); + + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + +// printf("ADS1255 result=%x\n\r", input_buffer.int16); + + return input_buffer.int16; +} + +int16_t ads1255_read_fast_single(void){ + + + union{ + uint8_t uint[2]; + int16_t int16; + } input_buffer; + +// uint8_t commandbuffer = ADS_RDATA; + +// spi_select_device(&SPIE, &spi_device_conf); +// spi_write_packet(&SPIE, &commandbuffer,1); +// delay_us(6.5); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[1] = spi_get(&SPIE); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[0] = spi_get(&SPIE); +// spi_deselect_device(&SPIE, &spi_device_conf); + + usart_spi_select_device(&USARTE1, &spi_device_conf); + usart_spi_transmit(&USARTE1, ADS_RDATA); + delay_us(6.5); + for (int i = 1; i >= 0; --i){ + while (usart_data_register_is_empty(&USARTE1) == false); + usart_put(&USARTE1, CONFIG_USART_SPI_DUMMY); + while (usart_rx_is_complete(&USARTE1) == false); + input_buffer.uint[i] = usart_get(&USARTE1); + } + while (!usart_tx_is_complete(&USARTE1)); + usart_clear_tx_complete(&USARTE1); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + + ads1255_standby(); + + #ifdef ADS1255_DBG + printf("ADS1255 result=%li\n\r", input_buffer.int16); + #endif + + return input_buffer.int16; +} + +int32_t ads1255_read(void){ + +/* irqflags_t flags;*/ + union{ + uint8_t uint[4]; + int32_t int32; + } input_buffer; + + //int32_t returnvalue = 0; + +/* while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3)));*/ + +/* flags = cpu_irq_save();*/ + +// spi_select_device(&SPIE, &spi_device_conf); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[2] = spi_get(&SPIE); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[1] = spi_get(&SPIE); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[0] = spi_get(&SPIE); +// +// spi_deselect_device(&SPIE, &spi_device_conf); +/* cpu_irq_restore(flags);*/ + + usart_spi_select_device(&USARTE1, &spi_device_conf); + for (int i = 2; i >= 0; --i) + { + while (usart_data_register_is_empty(&USARTE1) == false); + usart_put(&USARTE1, CONFIG_USART_SPI_DUMMY); + while (usart_rx_is_complete(&USARTE1) == false); + input_buffer.uint[i] = usart_get(&USARTE1); + } + while (!usart_tx_is_complete(&USARTE1)); + usart_clear_tx_complete(&USARTE1); + +// usart_spi_read_packet(&USARTE1, (uint8_t*)&(input_buffer.uint[2]),1); +// usart_spi_read_packet(&USARTE1, (uint8_t*)&(input_buffer.uint[1]),1); +// usart_spi_read_packet(&USARTE1, (uint8_t*)&(input_buffer.uint[0]),1); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + +// printf("%x, %x, %x\n\r", input_buffer.uint[2],input_buffer.uint[1], input_buffer.uint[0]); + + if (input_buffer.uint[2] > 0x7F) + input_buffer.uint[3] = 0xFF; + else + input_buffer.uint[3] = 0x0; + + #ifdef ADS1255_DBG + printf("ADS1255 result=%li\n\r", input_buffer.int32); + #endif + + if (input_buffer.int32 > ADS_OVERCURRENT_THRESHOLD || (-1*input_buffer.int32) > (ADS_OVERCURRENT_THRESHOLD)) + { + over_under[buffer_iter] = 1; + if (buffer_iter == (ADS_OVER_UNDER_SAMPLES - 1)) + buffer_iter = 0; + else + buffer_iter++; + } + else if (input_buffer.int32 < ADS_UNDERCURRENT_THRESHOLD && (input_buffer.int32*-1) < (ADS_UNDERCURRENT_THRESHOLD)) + { + over_under[buffer_iter] = -1; + if (buffer_iter == (ADS_OVER_UNDER_SAMPLES - 1)) + buffer_iter = 0; + else + buffer_iter++; + } + else + { + over_under[buffer_iter] = 0; + if (buffer_iter == (ADS_OVER_UNDER_SAMPLES - 1)) + buffer_iter = 0; + else + buffer_iter++; + } + + return input_buffer.int32; +} + +int32_t ads1255_read_fast24(void){ + + union{ + uint8_t uint[4]; + int32_t int32; + } input_buffer; + + input_buffer.int32 = 0; + +// spi_select_device(&SPIE, &spi_device_conf); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[2] = spi_get(&SPIE); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[1] = spi_get(&SPIE); +// spi_write_single(&SPIE, CONFIG_SPI_MASTER_DUMMY); +// while(!spi_is_rx_full(&SPIE)); +// input_buffer.uint[0] = spi_get(&SPIE); +// +// spi_deselect_device(&SPIE, &spi_device_conf); + + usart_spi_select_device(&USARTE1, &spi_device_conf); + for (int i = 2; i >= 0; --i){ + while (usart_data_register_is_empty(&USARTE1) == false); + usart_put(&USARTE1, CONFIG_USART_SPI_DUMMY); + while (usart_rx_is_complete(&USARTE1) == false); + input_buffer.uint[i] = usart_get(&USARTE1); + } + while (!usart_tx_is_complete(&USARTE1)); + usart_clear_tx_complete(&USARTE1); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + + if (input_buffer.uint[2] > 0x7F) + input_buffer.uint[3] = 0xFF; + else + input_buffer.uint[3] = 0x0; + + printf("%x, %x, %x\n\r", input_buffer.uint[2],input_buffer.uint[1], input_buffer.uint[0]); + + return input_buffer.int32; +} + + +void ads1255_reg_read(uint8_t address){ + uint8_t command_buffer[2]; + command_buffer[0] = address; + command_buffer[0] |= (1 << 4); + command_buffer[1] = 4; + uint8_t input_buffer[5]; + +// spi_select_device(&SPIE, &spi_device_conf); +// //delay_us(50); +// +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// +// spi_write_packet(&SPIE, &command_buffer[0], 2); +// delay_us(6.5); +// spi_read_packet(&SPIE, (uint8_t*) &input_buffer, 5); +// spi_deselect_device(&SPIE, &spi_device_conf); + + usart_spi_select_device(&USARTE1, &spi_device_conf); + + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + + usart_spi_write_packet(&USARTE1, &(command_buffer[0]), 2); + delay_us(6.5); + usart_spi_read_packet(&USARTE1, (uint8_t*) &input_buffer, 5); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + + for (int i=0;i<5;i++) + { + printf("ADS1255: Register %u=%.2x\n\r",i+1,input_buffer[i]); + } + + return; +} + +void ads1255_reset(){ +// uint8_t command_buffer = ADS_RESET; +// +// spi_select_device(&SPIE, &spi_device_conf); +// //delay_us(50); +// +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// spi_write_packet(&SPIE, (uint8_t*) &command_buffer, 1); +// + + usart_spi_select_device(&USARTE1, &spi_device_conf); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + usart_spi_transmit(&USARTE1, ADS_RESET); + + #ifdef ADS1255_DBG + printf("ADS1255: Sending RESET\n\r"); + printf("ADS1255: Waiting for calibration\n\r"); + #endif + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); + +// spi_deselect_device(&SPIE, &spi_device_conf); + + return; +} + +void ads1255_setup(uint8_t buff, uint8_t rate, uint8_t pga){ +// uint8_t ctrlbuffer = ADS_SDATAC; + uint8_t command_buffer[6] = {0x50,0x03,buff,0x01,pga,rate}; + +// spi_select_device(&SPIE, &spi_device_conf); +// //delay_us(50); +// +// //while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// +// spi_write_packet(&SPIE, &ctrlbuffer, 1); +// //while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// +// spi_write_packet(&SPIE, (uint8_t*)&command_buffer, 6); +// +// ctrlbuffer = ADS_SYNC; +// spi_write_packet(&SPIE, &ctrlbuffer, 1); +// ctrlbuffer = ADS_SELFCAL; +// spi_write_packet(&SPIE, &ctrlbuffer, 1); +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// +// +// spi_deselect_device(&SPIE, &spi_device_conf); + + usart_spi_select_device(&USARTE1, &spi_device_conf); +// usart_spi_transmit(&USARTE1, ADS_SDATAC); + usart_spi_transmit(&USARTE1, ADS_SDATAC); + usart_spi_write_packet(&USARTE1, (uint8_t*)&command_buffer, 6); + usart_spi_transmit(&USARTE1, ADS_SYNC); + usart_spi_transmit(&USARTE1, ADS_SELFCAL); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + + return; +} + +void ads1255_standby(void){ +// uint8_t ctrlbuffer = ADS_STANDBY; +// +// spi_select_device(&SPIE, &spi_device_conf); +// spi_write_packet(&SPIE, &ctrlbuffer, 1); +// spi_deselect_device(&SPIE, &spi_device_conf); + + usart_spi_select_device(&USARTE1, &spi_device_conf); + usart_spi_transmit(&USARTE1, ADS_STANDBY); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + + return; +} + +void ads1255_wakeup(void){ +// uint8_t ctrlbuffer = ADS_WAKEUP; +// +// spi_select_device(&SPIE, &spi_device_conf); +// spi_write_packet(&SPIE, &ctrlbuffer, 1); +// spi_deselect_device(&SPIE, &spi_device_conf); + + usart_spi_select_device(&USARTE1, &spi_device_conf); + usart_spi_transmit(&USARTE1, ADS_WAKEUP); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + + return; +} + +void ads1255_rdatac(void){ +// uint8_t ctrlbuffer = ADS_RDATAC; +// +// spi_select_device(&SPIE, &spi_device_conf); +// //delay_us(50); +// +// spi_write_packet(&SPIE, &ctrlbuffer, 1); +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// +// spi_deselect_device(&SPIE, &spi_device_conf); + + usart_spi_select_device(&USARTE1, &spi_device_conf); + usart_spi_transmit(&USARTE1, ADS_RDATAC); +// while(!usart_spi_is_rx_full(&USARTE1)); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + usart_spi_deselect_device(&USARTE1, &spi_device_conf); + + return; +} \ No newline at end of file diff --git a/DSTAT-temp/src/ads1255.h b/DSTAT-temp/src/ads1255.h new file mode 100644 index 0000000..f22bcaf --- /dev/null +++ b/DSTAT-temp/src/ads1255.h @@ -0,0 +1,82 @@ +/* + * ads1255.h + * + * Created: 05/03/2012 12:19:33 AM + * Author: mdryden + */ + + +#ifndef ADS1255_H_ +#define ADS1255_H_ + +//#define ADS1255_DBG + +#define ADS_WAKEUP 0x0 +#define ADS_RDATA 0x01 +#define ADS_RDATAC 0x03 +#define ADS_SDATAC 0x0f +#define ADS_SELFCAL 0xf0 +#define ADS_SELFOCAL 0xf1 +#define ADS_SELFGCAL 0xf2 +#define ADS_SYSOCAL 0xf3 +#define ADS_SYSGCAL 0xf4 +#define ADS_SYNC 0xfc +#define ADS_STANDBY 0xfd +#define ADS_RESET 0xfe + +#define ADS_DR_2_5 0b00000011 +#define ADS_DR_5 0b00010011 +#define ADS_DR_10 0b00100011 +#define ADS_DR_15 0b00110011 +#define ADS_DR_25 0b01000011 +#define ADS_DR_30 0b01010011 +#define ADS_DR_50 0b01100011 +#define ADS_DR_60 0b01110010 +#define ADS_DR_100 0b10000010 +#define ADS_DR_500 0b10010010 +#define ADS_DR_1000 0b10100001 +#define ADS_DR_2000 0b10110000 +#define ADS_DR_3750 0b11000000 +#define ADS_DR_7500 0b11010000 +#define ADS_DR_15000 0b11100000 +#define ADS_DR_30000 0b11110000 + +#define ADS_PGA_1 0b000 +#define ADS_PGA_2 0b001 +#define ADS_PGA_4 0b010 +#define ADS_PGA_8 0b011 +#define ADS_PGA_16 0b100 +#define ADS_PGA_32 0b101 +#define ADS_PGA_64 0b110 + +#define ADS_BUFF_OFF 0b0000 +#define ADS_BUFF_ON 0b0010 + +#define ADS_OVERCURRENT_THRESHOLD 6000000L +#define ADS_UNDERCURRENT_THRESHOLD 200000L +#define ADS_OVER_UNDER_SAMPLES 3 + + #include + #include + +int8_t over_under[ADS_OVER_UNDER_SAMPLES]; + +void ads1255_sync(void); +void ads1255_init_pins(void); +void ads1255_init_module(void); +int32_t ads1255_single_read(void); +int32_t ads1255_read(void); +int16_t ads1255_read_fast(void); +int16_t ads1255_read_fast_single(void); +int32_t ads1255_read_fast24(void); +void ads1255_reg_read(uint8_t address); +void ads1255_reset(void); +void ads1255_setup(uint8_t buff, uint8_t rate, uint8_t pga); +void ads1255_standby(void); +void ads1255_wakeup(void); +void ads1255_rdatac(void); + + + +#endif /* ADS1255_H_ */ + diff --git a/DSTAT-temp/src/asf.h b/DSTAT-temp/src/asf.h new file mode 100644 index 0000000..4d455ae --- /dev/null +++ b/DSTAT-temp/src/asf.h @@ -0,0 +1,120 @@ +/** + * \file + * + * \brief Autogenerated API include file for the Atmel Software Framework (ASF) + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef ASF_H +#define ASF_H + +/* + * This file includes all API header files for the selected drivers from ASF. + * Note: There might be duplicate includes required by more than one driver. + * + * The file is automatically generated and will be re-written when + * running the ASF driver selector tool. Any changes will be discarded. + */ + +// From module: CPU specific features +#include +#include + +// From module: Delay routines +#include + +// From module: Generic board support +#include + +// From module: IOPORT - General purpose I/O service +#include + +// From module: Interrupt management - XMEGA implementation +#include + +// From module: NVM - Non Volatile Memory +#include + +// From module: PMIC - Programmable Multi-level Interrupt Controller +#include + +// From module: Part identification macros +#include + +// From module: RTC - Real Time Counter +#include + +// From module: SPI - XMEGA implementation +#include +#include + +// From module: Sleep Controller driver +#include + +// From module: Sleep manager - XMEGA A/AU/B/D implementation +#include +#include + +// From module: System Clock Control - XMEGA A1U/A3U/A3BU/A4U implementation +#include + +// From module: TC - Timer Counter +#include + +// From module: USART - Universal Synchronous/Asynchronous Receiver/Transmitter +#include + +// From module: USB CDC Protocol +#include + +// From module: USB Device CDC (Single Interface Device) +#include + +// From module: USB Device CDC Standard I/O (stdio) - AVR implementation +#include + +// From module: USB Device Stack Core (Common API) +#include +#include + +// From module: XMEGA compiler driver +#include +#include + +#endif // ASF_H diff --git a/DSTAT-temp/src/asf/common/boards/board.h b/DSTAT-temp/src/asf/common/boards/board.h new file mode 100644 index 0000000..bb05b36 --- /dev/null +++ b/DSTAT-temp/src/asf/common/boards/board.h @@ -0,0 +1,291 @@ +/** + * \file + * + * \brief Standard board header file. + * + * This file includes the appropriate board header file according to the + * defined board (parameter BOARD). + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/** + * \defgroup group_common_boards Generic board support + * + * The generic board support module includes board-specific definitions + * and function prototypes, such as the board initialization function. + * + * \{ + */ + +#include "compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! \name Base Boards + */ +//! @{ +#define EVK1100 1 //!< AT32UC3A EVK1100 board. +#define EVK1101 2 //!< AT32UC3B EVK1101 board. +#define UC3C_EK 3 //!< AT32UC3C UC3C_EK board. +#define EVK1104 4 //!< AT32UC3A3 EVK1104 board. +#define EVK1105 5 //!< AT32UC3A EVK1105 board. +#define STK600_RCUC3L0 6 //!< STK600 RCUC3L0 board. +#define UC3L_EK 7 //!< AT32UC3L-EK board. +#define XPLAIN 8 //!< ATxmega128A1 Xplain board. +#define STK600_RC064X 10 //!< ATxmega256A3 STK600 board. +#define STK600_RC100X 11 //!< ATxmega128A1 STK600 board. +#define UC3_A3_XPLAINED 13 //!< ATUC3A3 UC3-A3 Xplained board. +#define UC3_L0_XPLAINED 15 //!< ATUC3L0 UC3-L0 Xplained board. +#define STK600_RCUC3D 16 //!< STK600 RCUC3D board. +#define STK600_RCUC3C0 17 //!< STK600 RCUC3C board. +#define XMEGA_B1_XPLAINED 18 //!< ATxmega128B1 Xplained board. +#define XMEGA_A1_XPLAINED 19 //!< ATxmega128A1 Xplain-A1 board. +#define STK600_RCUC3L4 21 //!< ATUCL4 STK600 board +#define UC3_L0_XPLAINED_BC 22 //!< ATUC3L0 UC3-L0 Xplained board controller board +#define MEGA1284P_XPLAINED_BC 23 //!< ATmega1284P-Xplained board controller board +#define STK600_RC044X 24 //!< STK600 with RC044X routing card board. +#define STK600_RCUC3B0 25 //!< STK600 RCUC3B0 board. +#define UC3_L0_QT600 26 //!< QT600 UC3L0 MCU board. +#define XMEGA_A3BU_XPLAINED 27 //!< ATxmega256A3BU Xplained board. +#define STK600_RC064X_LCDX 28 //!< XMEGAB3 STK600 RC064X LCDX board. +#define STK600_RC100X_LCDX 29 //!< XMEGAB1 STK600 RC100X LCDX board. +#define UC3B_BOARD_CONTROLLER 30 //!< AT32UC3B1 board controller for Atmel boards +#define RZ600 31 //!< AT32UC3A RZ600 MCU board +#define SAM3S_EK 32 //!< SAM3S-EK board. +#define SAM3U_EK 33 //!< SAM3U-EK board. +#define SAM3X_EK 34 //!< SAM3X-EK board. +#define SAM3N_EK 35 //!< SAM3N-EK board. +#define SAM3S_EK2 36 //!< SAM3S-EK2 board. +#define SAM4S_EK 37 //!< SAM4S-EK board. +#define STK600_RCUC3A0 38 //!< STK600 RCUC3A0 board. +#define STK600_MEGA 39 //!< STK600 MEGA board. +#define MEGA_1284P_XPLAINED 40 //!< ATmega1284P Xplained board. +#define SAM4S_XPLAINED 41 //!< SAM4S Xplained board. +#define ATXMEGA128A1_QT600 42 //!< QT600 ATXMEGA128A1 MCU board. +#define ARDUINO_DUE_X 43 //!< Arduino Due/X board. +#define STK600_RCUC3L3 44 //!< ATUCL3 STK600 board +#define SAM4L_EK 45 //!< SAM4L-EK board. +#define SIMULATOR_XMEGA_A1 97 //!< Simulator for XMEGA A1 devices +#define AVR_SIMULATOR_UC3 98 //!< AVR SIMULATOR for AVR UC3 device family. +#define USER_BOARD 99 //!< User-reserved board (if any). +#define DUMMY_BOARD 100 //!< Dummy board to support board-independent applications (e.g. bootloader) +//! @} + +/*! \name Extension Boards + */ +//! @{ +#define EXT1102 1 //!< AT32UC3B EXT1102 board +#define MC300 2 //!< AT32UC3 MC300 board +#define SENSORS_XPLAINED_INERTIAL_1 3 //!< Xplained inertial sensor board 1 +#define SENSORS_XPLAINED_INERTIAL_2 4 //!< Xplained inertial sensor board 2 +#define SENSORS_XPLAINED_PRESSURE_1 5 //!< Xplained pressure sensor board +#define SENSORS_XPLAINED_LIGHTPROX_1 6 //!< Xplained light & proximity sensor board +#define SENSORS_XPLAINED_INERTIAL_A1 7 //!< Xplained inertial sensor board "A" +#define RZ600_AT86RF231 8 //!< AT86RF231 RF board in RZ600 +#define RZ600_AT86RF230B 9 //!< AT86RF231 RF board in RZ600 +#define RZ600_AT86RF212 10 //!< AT86RF231 RF board in RZ600 +#define SENSORS_XPLAINED_BREADBOARD 11 //!< Xplained sensor development breadboard +#define SECURITY_XPLAINED 12 //!< Xplained ATSHA204 board +#define USER_EXT_BOARD 99 //!< User-reserved extension board (if any). +//! @} + +#if BOARD == EVK1100 +# include "evk1100/evk1100.h" +#elif BOARD == EVK1101 +# include "evk1101/evk1101.h" +#elif BOARD == UC3C_EK +# include "uc3c_ek/uc3c_ek.h" +#elif BOARD == EVK1104 +# include "evk1104/evk1104.h" +#elif BOARD == EVK1105 +# include "evk1105/evk1105.h" +#elif BOARD == STK600_RCUC3L0 +# include "stk600/rcuc3l0/stk600_rcuc3l0.h" +#elif BOARD == UC3L_EK +# include "uc3l_ek/uc3l_ek.h" +#elif BOARD == STK600_RCUC3L4 +# include "stk600/rcuc3l4/stk600_rcuc3l4.h" +#elif BOARD == XPLAIN +# include "xplain/xplain.h" +#elif BOARD == STK600_MEGA + /*No header-file to include*/ +#elif BOARD == STK600_RC044X +# include "stk600/rc044x/stk600_rc044x.h" +#elif BOARD == STK600_RC064X +# include "stk600/rc064x/stk600_rc064x.h" +#elif BOARD == STK600_RC100X +# include "stk600/rc100x/stk600_rc100x.h" +#elif BOARD == UC3_A3_XPLAINED +# include "uc3_a3_xplained/uc3_a3_xplained.h" +#elif BOARD == UC3_L0_XPLAINED +# include "uc3_l0_xplained/uc3_l0_xplained.h" +#elif BOARD == STK600_RCUC3B0 +# include "stk600/rcuc3b0/stk600_rcuc3b0.h" +#elif BOARD == STK600_RCUC3D +# include "stk600/rcuc3d/stk600_rcuc3d.h" +#elif BOARD == STK600_RCUC3C0 +# include "stk600/rcuc3c0/stk600_rcuc3c0.h" +#elif BOARD == XMEGA_B1_XPLAINED +# include "xmega_b1_xplained/xmega_b1_xplained.h" +#elif BOARD == STK600_RC064X_LCDX +# include "stk600/rc064x_lcdx/stk600_rc064x_lcdx.h" +#elif BOARD == STK600_RC100X_LCDX +# include "stk600/rc100x_lcdx/stk600_rc100x_lcdx.h" +#elif BOARD == XMEGA_A1_XPLAINED +# include "xmega_a1_xplained/xmega_a1_xplained.h" +#elif BOARD == UC3_L0_XPLAINED_BC +# include "uc3_l0_xplained_bc/uc3_l0_xplained_bc.h" +#elif BOARD == SAM3S_EK +# include "sam3s_ek/sam3s_ek.h" +# include "system_sam3s.h" +#elif BOARD == SAM3S_EK2 +# include "sam3s_ek2/sam3s_ek2.h" +# include "system_sam3sd8.h" +#elif BOARD == SAM3U_EK +# include "sam3u_ek/sam3u_ek.h" +# include "system_sam3u.h" +#elif BOARD == SAM3X_EK +# include "sam3x_ek/sam3x_ek.h" +# include "system_sam3x.h" +#elif BOARD == SAM3N_EK +# include "sam3n_ek/sam3n_ek.h" +# include "system_sam3n.h" +#elif BOARD == SAM4S_EK +# include "sam4s_ek/sam4s_ek.h" +# include "system_sam4s.h" +#elif BOARD == SAM4S_XPLAINED +# include "sam4s_xplained/sam4s_xplained.h" +# include "system_sam4s.h" +#elif BOARD == MEGA_1284P_XPLAINED + /*No header-file to include*/ +#elif BOARD == ARDUINO_DUE_X +# include "arduino_due_x/arduino_due_x.h" +# include "system_sam3x.h" +#elif BOARD == SAM4L_EK +# include "sam4l_ek/sam4l_ek.h" +#elif BOARD == MEGA1284P_XPLAINED_BC +# include "mega1284p_xplained_bc/mega1284p_xplained_bc.h" +#elif BOARD == UC3_L0_QT600 +# include "uc3_l0_qt600/uc3_l0_qt600.h" +#elif BOARD == XMEGA_A3BU_XPLAINED +# include "xmega_a3bu_xplained/xmega_a3bu_xplained.h" +#elif BOARD == UC3B_BOARD_CONTROLLER +# include "uc3b_board_controller/uc3b_board_controller.h" +#elif BOARD == RZ600 +# include "rz600/rz600.h" +#elif BOARD == STK600_RCUC3A0 +# include "stk600/rcuc3a0/stk600_rcuc3a0.h" +#elif BOARD == ATXMEGA128A1_QT600 +# include "atxmega128a1_qt600/atxmega128a1_qt600.h" +#elif BOARD == STK600_RCUC3L3 + #include "stk600/rcuc3l3/stk600_rcuc3l3.h" +#elif BOARD == SIMULATOR_XMEGA_A1 +# include "simulator/xmega_a1/simulator_xmega_a1.h" +#elif BOARD == AVR_SIMULATOR_UC3 +# include "avr_simulator_uc3/avr_simulator_uc3.h" +#elif BOARD == USER_BOARD + // User-reserved area: #include the header file of your board here (if any). +# include "user_board.h" +#elif BOARD == DUMMY_BOARD +# include "dummy/dummy_board.h" +#else +# error No known AVR board defined +#endif + +#if (defined EXT_BOARD) +# if EXT_BOARD == MC300 +# include "mc300/mc300.h" +# elif (EXT_BOARD == SENSORS_XPLAINED_INERTIAL_1) || \ + (EXT_BOARD == SENSORS_XPLAINED_INERTIAL_2) || \ + (EXT_BOARD == SENSORS_XPLAINED_INERTIAL_A1) || \ + (EXT_BOARD == SENSORS_XPLAINED_PRESSURE_1) || \ + (EXT_BOARD == SENSORS_XPLAINED_LIGHTPROX_1) || \ + (EXT_BOARD == SENSORS_XPLAINED_BREADBOARD) +# include "sensors_xplained/sensors_xplained.h" +# elif EXT_BOARD == RZ600_AT86RF231 +# include "at86rf231/at86rf231.h" +# elif EXT_BOARD == RZ600_AT86RF230B +# include "at86rf230b/at86rf230b.h" +# elif EXT_BOARD == RZ600_AT86RF212 +# include "at86rf212/at86rf212.h" +# elif EXT_BOARD == SECURITY_XPLAINED +# include "security_xplained.h" +# elif EXT_BOARD == USER_EXT_BOARD + // User-reserved area: #include the header file of your extension board here + // (if any). +# endif +#endif + + +#if (defined(__GNUC__) && defined(__AVR32__)) || (defined(__ICCAVR32__) || defined(__AAVR32__)) +#ifdef __AVR32_ABI_COMPILER__ // Automatically defined when compiling for AVR32, not when assembling. + +/*! \brief This function initializes the board target resources + * + * This function should be called to ensure proper initialization of the target + * board hardware connected to the part. + */ +extern void board_init(void); + +#endif // #ifdef __AVR32_ABI_COMPILER__ +#else +/*! \brief This function initializes the board target resources + * + * This function should be called to ensure proper initialization of the target + * board hardware connected to the part. + */ +extern void board_init(void); +#endif + + +#ifdef __cplusplus +} +#endif + +/** + * \} + */ + +#endif // _BOARD_H_ diff --git a/DSTAT-temp/src/asf/common/boards/user_board/init.c b/DSTAT-temp/src/asf/common/boards/user_board/init.c new file mode 100644 index 0000000..62dec1e --- /dev/null +++ b/DSTAT-temp/src/asf/common/boards/user_board/init.c @@ -0,0 +1,18 @@ +/** + * \file + * + * \brief User board initialization template + * + */ + +#include +#include +#include + +void board_init(void) +{ + /* This function is meant to contain board-specific initialization code + * for, e.g., the I/O pins. The initialization can rely on application- + * specific board configuration, found in conf_board.h. + */ +} diff --git a/DSTAT-temp/src/asf/common/boards/user_board/user_board.h b/DSTAT-temp/src/asf/common/boards/user_board/user_board.h new file mode 100644 index 0000000..c2d29e1 --- /dev/null +++ b/DSTAT-temp/src/asf/common/boards/user_board/user_board.h @@ -0,0 +1,37 @@ +/** + * \file + * + * \brief User board definition template + * + */ + + /* This file is intended to contain definitions and configuration details for + * features and devices that are available on the board, e.g., frequency and + * startup time for an external crystal, external memory devices, LED and USART + * pins. + */ + +#ifndef USER_BOARD_H +#define USER_BOARD_H + +#include + +// External oscillator settings. +// Uncomment and set correct values if external oscillator is used. + +// External oscillator frequency +//#define BOARD_XOSC_HZ 8000000 + +// External oscillator type. +//!< External clock signal +//#define BOARD_XOSC_TYPE XOSC_TYPE_EXTERNAL +//!< 32.768 kHz resonator on TOSC +//#define BOARD_XOSC_TYPE XOSC_TYPE_32KHZ +//!< 0.4 to 16 MHz resonator on XTALS +//#define BOARD_XOSC_TYPE XOSC_TYPE_XTAL + +// External oscillator startup time +//#define BOARD_XOSC_STARTUP_US 500000 + + +#endif // USER_BOARD_H diff --git a/DSTAT-temp/src/asf/common/services/clock/genclk.h b/DSTAT-temp/src/asf/common/services/clock/genclk.h new file mode 100644 index 0000000..00d39f0 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/clock/genclk.h @@ -0,0 +1,176 @@ +/** + * \file + * + * \brief Generic clock management + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef CLK_GENCLK_H_INCLUDED +#define CLK_GENCLK_H_INCLUDED + +#include "parts.h" + +#if SAM3S +# include "sam3s/genclk.h" +#elif SAM3U +# include "sam3u/genclk.h" +#elif SAM3N +# include "sam3n/genclk.h" +#elif SAM3XA +# include "sam3x/genclk.h" +#elif SAM4S +# include "sam4s/genclk.h" +#elif SAM4L +# include "sam4l/genclk.h" +#elif (UC3A0 || UC3A1) +# include "uc3a0_a1/genclk.h" +#elif UC3A3 +# include "uc3a3_a4/genclk.h" +#elif UC3B +# include "uc3b0_b1/genclk.h" +#elif UC3C +# include "uc3c/genclk.h" +#elif UC3D +# include "uc3d/genclk.h" +#elif UC3L +# include "uc3l/genclk.h" +#else +# error Unsupported chip type +#endif + +/** + * \ingroup clk_group + * \defgroup genclk_group Generic Clock Management + * + * Generic clocks are configurable clocks which run outside the system + * clock domain. They are often connected to peripherals which have an + * asynchronous component running independently of the bus clock, e.g. + * USB controllers, low-power timers and RTCs, etc. + * + * Note that not all platforms have support for generic clocks; on such + * platforms, this API will not be available. + * + * @{ + */ + +/** + * \def GENCLK_DIV_MAX + * \brief Maximum divider supported by the generic clock implementation + */ +/** + * \enum genclk_source + * \brief Generic clock source ID + * + * Each generic clock may be generated from a different clock source. + * These are the available alternatives provided by the chip. + */ + +//! \name Generic clock configuration +//@{ +/** + * \struct genclk_config + * \brief Hardware representation of a set of generic clock parameters + */ +/** + * \fn void genclk_config_defaults(struct genclk_config *cfg, + * unsigned int id) + * \brief Initialize \a cfg to the default configuration for the clock + * identified by \a id. + */ +/** + * \fn void genclk_config_read(struct genclk_config *cfg, unsigned int id) + * \brief Read the currently active configuration of the clock + * identified by \a id into \a cfg. + */ +/** + * \fn void genclk_config_write(const struct genclk_config *cfg, + * unsigned int id) + * \brief Activate the configuration \a cfg on the clock identified by + * \a id. + */ +/** + * \fn void genclk_config_set_source(struct genclk_config *cfg, + * enum genclk_source src) + * \brief Select a new source clock \a src in configuration \a cfg. + */ +/** + * \fn void genclk_config_set_divider(struct genclk_config *cfg, + * unsigned int divider) + * \brief Set a new \a divider in configuration \a cfg. + */ +/** + * \fn void genclk_enable_source(enum genclk_source src) + * \brief Enable the source clock \a src used by a generic clock. + */ + //@} + +//! \name Enabling and disabling Generic Clocks +//@{ +/** + * \fn void genclk_enable(const struct genclk_config *cfg, unsigned int id) + * \brief Activate the configuration \a cfg on the clock identified by + * \a id and enable it. + */ +/** + * \fn void genclk_disable(unsigned int id) + * \brief Disable the generic clock identified by \a id. + */ +//@} + +/** + * \brief Enable the configuration defined by \a src and \a divider + * for the generic clock identified by \a id. + * + * \param id The ID of the generic clock. + * \param src The source clock of the generic clock. + * \param divider The divider used to generate the generic clock. + */ +static inline void genclk_enable_config(unsigned int id, enum genclk_source src, unsigned int divider) +{ + struct genclk_config gcfg; + + genclk_config_defaults(&gcfg, id); + genclk_enable_source(src); + genclk_config_set_source(&gcfg, src); + genclk_config_set_divider(&gcfg, divider); + genclk_enable(&gcfg, id); +} + +//! @} + +#endif /* CLK_GENCLK_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/common/services/clock/osc.h b/DSTAT-temp/src/asf/common/services/clock/osc.h new file mode 100644 index 0000000..d6b4ab0 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/clock/osc.h @@ -0,0 +1,162 @@ +/** + * \file + * + * \brief Oscillator management + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef OSC_H_INCLUDED +#define OSC_H_INCLUDED + +#include "parts.h" +#include "conf_clock.h" + +#if SAM3S +# include "sam3s/osc.h" +#elif SAM3XA +# include "sam3x/osc.h" +#elif SAM3U +# include "sam3u/osc.h" +#elif SAM3N +# include "sam3n/osc.h" +#elif SAM4S +# include "sam4s/osc.h" +#elif SAM4L +# include "sam4l/osc.h" +#elif (UC3A0 || UC3A1) +# include "uc3a0_a1/osc.h" +#elif UC3A3 +# include "uc3a3_a4/osc.h" +#elif UC3B +# include "uc3b0_b1/osc.h" +#elif UC3C +# include "uc3c/osc.h" +#elif UC3D +# include "uc3d/osc.h" +#elif UC3L +# include "uc3l/osc.h" +#elif XMEGA +# include "xmega/osc.h" +#else +# error Unsupported chip type +#endif + +/** + * \ingroup clk_group + * \defgroup osc_group Oscillator Management + * + * This group contains functions and definitions related to configuring + * and enabling/disabling on-chip oscillators. Internal RC-oscillators, + * external crystal oscillators and external clock generators are + * supported by this module. What all of these have in common is that + * they swing at a fixed, nominal frequency which is normally not + * adjustable. + * + * \par Example: Enabling an oscillator + * + * The following example demonstrates how to enable the external + * oscillator on XMEGA A and wait for it to be ready to use. The + * oscillator identifiers are platform-specific, so while the same + * procedure is used on all platforms, the parameter to osc_enable() + * will be different from device to device. + * \code + osc_enable(OSC_ID_XOSC); + osc_wait_ready(OSC_ID_XOSC); \endcode + * + * \section osc_group_board Board-specific Definitions + * If external oscillators are used, the board code must provide the + * following definitions for each of those: + * - \b BOARD__HZ: The nominal frequency of the oscillator. + * - \b BOARD__STARTUP_US: The startup time of the + * oscillator in microseconds. + * - \b BOARD__TYPE: The type of oscillator connected, i.e. + * whether it's a crystal or external clock, and sometimes what kind + * of crystal it is. The meaning of this value is platform-specific. + * + * @{ + */ + +//! \name Oscillator Management +//@{ +/** + * \fn void osc_enable(uint8_t id) + * \brief Enable oscillator \a id + * + * The startup time and mode value is automatically determined based on + * definitions in the board code. + */ +/** + * \fn void osc_disable(uint8_t id) + * \brief Disable oscillator \a id + */ +/** + * \fn osc_is_ready(uint8_t id) + * \brief Determine whether oscillator \a id is ready. + * \retval true Oscillator \a id is running and ready to use as a clock + * source. + * \retval false Oscillator \a id is not running. + */ +/** + * \fn uint32_t osc_get_rate(uint8_t id) + * \brief Return the frequency of oscillator \a id in Hz + */ + +#ifndef __ASSEMBLY__ + +/** + * \brief Wait until the oscillator identified by \a id is ready + * + * This function will busy-wait for the oscillator identified by \a id + * to become stable and ready to use as a clock source. + * + * \param id A number identifying the oscillator to wait for. + */ +static inline void osc_wait_ready(uint8_t id) +{ + while (!osc_is_ready(id)) { + /* Do nothing */ + } +} + +#endif /* __ASSEMBLY__ */ + +//@} + +//! @} + +#endif /* OSC_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/common/services/clock/pll.h b/DSTAT-temp/src/asf/common/services/clock/pll.h new file mode 100644 index 0000000..386eb40 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/clock/pll.h @@ -0,0 +1,318 @@ +/** + * \file + * + * \brief PLL management + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef CLK_PLL_H_INCLUDED +#define CLK_PLL_H_INCLUDED + +#include "parts.h" +#include "conf_clock.h" + +#if SAM3S +# include "sam3s/pll.h" +#elif SAM3XA +# include "sam3x/pll.h" +#elif SAM3U +# include "sam3u/pll.h" +#elif SAM3N +# include "sam3n/pll.h" +#elif SAM4S +# include "sam4s/pll.h" +#elif SAM4L +# include "sam4l/pll.h" +#elif (UC3A0 || UC3A1) +# include "uc3a0_a1/pll.h" +#elif UC3A3 +# include "uc3a3_a4/pll.h" +#elif UC3B +# include "uc3b0_b1/pll.h" +#elif UC3C +# include "uc3c/pll.h" +#elif UC3D +# include "uc3d/pll.h" +#elif (UC3L0128 || UC3L0256 || UC3L3_L4) +# include "uc3l/pll.h" +#elif XMEGA +# include "xmega/pll.h" +#else +# error Unsupported chip type +#endif + +/** + * \ingroup clk_group + * \defgroup pll_group PLL Management + * + * This group contains functions and definitions related to configuring + * and enabling/disabling on-chip PLLs. A PLL will take an input signal + * (the \em source), optionally divide the frequency by a configurable + * \em divider, and then multiply the frequency by a configurable \em + * multiplier. + * + * Some devices don't support input dividers; specifying any other + * divisor than 1 on these devices will result in an assertion failure. + * Other devices may have various restrictions to the frequency range of + * the input and output signals. + * + * \par Example: Setting up PLL0 with default parameters + * + * The following example shows how to configure and enable PLL0 using + * the default parameters specified using the configuration symbols + * listed above. + * \code + pll_enable_config_defaults(0); \endcode + * + * To configure, enable PLL0 using the default parameters and to disable + * a specific feature like Wide Bandwidth Mode (a UC3A3-specific + * PLL option.), you can use this initialization process. + * \code + struct pll_config pllcfg; + if (pll_is_locked(pll_id)) { + return; // Pll already running + } + pll_enable_source(CONFIG_PLL0_SOURCE); + pll_config_defaults(&pllcfg, 0); + pll_config_set_option(&pllcfg, PLL_OPT_WBM_DISABLE); + pll_enable(&pllcfg, 0); + pll_wait_for_lock(0); \endcode + * + * When the last function call returns, PLL0 is ready to be used as the + * main system clock source. + * + * \section pll_group_config Configuration Symbols + * + * Each PLL has a set of default parameters determined by the following + * configuration symbols in the application's configuration file: + * - \b CONFIG_PLLn_SOURCE: The default clock source connected to the + * input of PLL \a n. Must be one of the values defined by the + * #pll_source enum. + * - \b CONFIG_PLLn_MUL: The default multiplier (loop divider) of PLL + * \a n. + * - \b CONFIG_PLLn_DIV: The default input divider of PLL \a n. + * + * These configuration symbols determine the result of calling + * pll_config_defaults() and pll_get_default_rate(). + * + * @{ + */ + +//! \name Chip-specific PLL characteristics +//@{ +/** + * \def PLL_MAX_STARTUP_CYCLES + * \brief Maximum PLL startup time in number of slow clock cycles + */ +/** + * \def NR_PLLS + * \brief Number of on-chip PLLs + */ + +/** + * \def PLL_MIN_HZ + * \brief Minimum frequency that the PLL can generate + */ +/** + * \def PLL_MAX_HZ + * \brief Maximum frequency that the PLL can generate + */ +/** + * \def PLL_NR_OPTIONS + * \brief Number of PLL option bits + */ +//@} + +/** + * \enum pll_source + * \brief PLL clock source + */ + +//! \name PLL configuration +//@{ + +/** + * \struct pll_config + * \brief Hardware-specific representation of PLL configuration. + * + * This structure contains one or more device-specific values + * representing the current PLL configuration. The contents of this + * structure is typically different from platform to platform, and the + * user should not access any fields except through the PLL + * configuration API. + */ + +/** + * \fn void pll_config_init(struct pll_config *cfg, + * enum pll_source src, unsigned int div, unsigned int mul) + * \brief Initialize PLL configuration from standard parameters. + * + * \note This function may be defined inline because it is assumed to be + * called very few times, and usually with constant parameters. Inlining + * it will in such cases reduce the code size significantly. + * + * \param cfg The PLL configuration to be initialized. + * \param src The oscillator to be used as input to the PLL. + * \param div PLL input divider. + * \param mul PLL loop divider (i.e. multiplier). + * + * \return A configuration which will make the PLL run at + * (\a mul / \a div) times the frequency of \a src + */ +/** + * \def pll_config_defaults(cfg, pll_id) + * \brief Initialize PLL configuration using default parameters. + * + * After this function returns, \a cfg will contain a configuration + * which will make the PLL run at (CONFIG_PLLx_MUL / CONFIG_PLLx_DIV) + * times the frequency of CONFIG_PLLx_SOURCE. + * + * \param cfg The PLL configuration to be initialized. + * \param pll_id Use defaults for this PLL. + */ +/** + * \def pll_get_default_rate(pll_id) + * \brief Get the default rate in Hz of \a pll_id + */ +/** + * \fn void pll_config_set_option(struct pll_config *cfg, + * unsigned int option) + * \brief Set the PLL option bit \a option in the configuration \a cfg. + * + * \param cfg The PLL configuration to be changed. + * \param option The PLL option bit to be set. + */ +/** + * \fn void pll_config_clear_option(struct pll_config *cfg, + * unsigned int option) + * \brief Clear the PLL option bit \a option in the configuration \a cfg. + * + * \param cfg The PLL configuration to be changed. + * \param option The PLL option bit to be cleared. + */ +/** + * \fn void pll_config_read(struct pll_config *cfg, unsigned int pll_id) + * \brief Read the currently active configuration of \a pll_id. + * + * \param cfg The configuration object into which to store the currently + * active configuration. + * \param pll_id The ID of the PLL to be accessed. + */ +/** + * \fn void pll_config_write(const struct pll_config *cfg, + * unsigned int pll_id) + * \brief Activate the configuration \a cfg on \a pll_id + * + * \param cfg The configuration object representing the PLL + * configuration to be activated. + * \param pll_id The ID of the PLL to be updated. + */ + +//@} + +//! \name Interaction with the PLL hardware +//@{ +/** + * \fn void pll_enable(const struct pll_config *cfg, + * unsigned int pll_id) + * \brief Activate the configuration \a cfg and enable PLL \a pll_id. + * + * \param cfg The PLL configuration to be activated. + * \param pll_id The ID of the PLL to be enabled. + */ +/** + * \fn void pll_disable(unsigned int pll_id) + * \brief Disable the PLL identified by \a pll_id. + * + * After this function is called, the PLL identified by \a pll_id will + * be disabled. The PLL configuration stored in hardware may be affected + * by this, so if the caller needs to restore the same configuration + * later, it should either do a pll_config_read() before disabling the + * PLL, or remember the last configuration written to the PLL. + * + * \param pll_id The ID of the PLL to be disabled. + */ +/** + * \fn bool pll_is_locked(unsigned int pll_id) + * \brief Determine whether the PLL is locked or not. + * + * \param pll_id The ID of the PLL to check. + * + * \retval true The PLL is locked and ready to use as a clock source + * \retval false The PLL is not yet locked, or has not been enabled. + */ +/** + * \fn void pll_enable_source(enum pll_source src) + * \brief Enable the source of the pll. + * The source is enabled, if the source is not already running. + * + * \param src The ID of the PLL source to enable. + */ +/** + * \fn void pll_enable_config_defaults(unsigned int pll_id) + * \brief Enable the pll with the default configuration. + * PLL is enabled, if the PLL is not already locked. + * + * \param pll_id The ID of the PLL to enable. + */ + +/** + * \brief Wait for PLL \a pll_id to become locked + * + * \todo Use a timeout to avoid waiting forever and hanging the system + * + * \param pll_id The ID of the PLL to wait for. + * + * \retval STATUS_OK The PLL is now locked. + * \retval ERR_TIMEOUT Timed out waiting for PLL to become locked. + */ +static inline int pll_wait_for_lock(unsigned int pll_id) +{ + Assert(pll_id < NR_PLLS); + + while (!pll_is_locked(pll_id)) { + /* Do nothing */ + } + + return 0; +} + +//@} +//! @} + +#endif /* CLK_PLL_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/common/services/clock/sysclk.h b/DSTAT-temp/src/asf/common/services/clock/sysclk.h new file mode 100644 index 0000000..e628c99 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/clock/sysclk.h @@ -0,0 +1,169 @@ +/** + * \file + * + * \brief System clock management + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef SYSCLK_H_INCLUDED +#define SYSCLK_H_INCLUDED + +#include "parts.h" +#include "conf_clock.h" + +#if SAM3S +# include "sam3s/sysclk.h" +#elif SAM3U +# include "sam3u/sysclk.h" +#elif SAM3N +# include "sam3n/sysclk.h" +#elif SAM3XA +# include "sam3x/sysclk.h" +#elif SAM4S +# include "sam4s/sysclk.h" +#elif SAM4L +# include "sam4l/sysclk.h" +#elif (UC3A0 || UC3A1) +# include "uc3a0_a1/sysclk.h" +#elif UC3A3 +# include "uc3a3_a4/sysclk.h" +#elif UC3B +# include "uc3b0_b1/sysclk.h" +#elif UC3C +# include "uc3c/sysclk.h" +#elif UC3D +# include "uc3d/sysclk.h" +#elif UC3L +# include "uc3l/sysclk.h" +#elif XMEGA +# include "xmega/sysclk.h" +#else +# error Unsupported chip type +#endif + +/** + * \defgroup clk_group Clock Management + */ + +/** + * \ingroup clk_group + * \defgroup sysclk_group System Clock Management + * + * See \ref sysclk_quickstart. + * + * The sysclk API covers the system clock and all + * clocks derived from it. The system clock is a chip-internal clock on + * which all synchronous clocks, i.e. CPU and bus/peripheral + * clocks, are based. The system clock is typically generated from one + * of a variety of sources, which may include crystal and RC oscillators + * as well as PLLs. The clocks derived from the system clock are + * sometimes also known as synchronous clocks, since they + * always run synchronously with respect to each other, as opposed to + * generic clocks which may run from different oscillators or + * PLLs. + * + * Most applications should simply call sysclk_init() to initialize + * everything related to the system clock and its source (oscillator, + * PLL or DFLL), and leave it at that. More advanced applications, and + * platform-specific drivers, may require additional services from the + * clock system, some of which may be platform-specific. + * + * \section sysclk_group_platform Platform Dependencies + * + * The sysclk API is partially chip- or platform-specific. While all + * platforms provide mostly the same functionality, there are some + * variations around how different bus types and clock tree structures + * are handled. + * + * The following functions are available on all platforms with the same + * parameters and functionality. These functions may be called freely by + * portable applications, drivers and services: + * - sysclk_init() + * - sysclk_set_source() + * - sysclk_get_main_hz() + * - sysclk_get_cpu_hz() + * - sysclk_get_peripheral_bus_hz() + * + * The following functions are available on all platforms, but there may + * be variations in the function signature (i.e. parameters) and + * behavior. These functions are typically called by platform-specific + * parts of drivers, and applications that aren't intended to be + * portable: + * - sysclk_enable_peripheral_clock() + * - sysclk_disable_peripheral_clock() + * - sysclk_enable_module() + * - sysclk_disable_module() + * - sysclk_module_is_enabled() + * - sysclk_set_prescalers() + * + * All other functions should be considered platform-specific. + * Enabling/disabling clocks to specific peripherals as well as + * determining the speed of these clocks should be done by calling + * functions provided by the driver for that peripheral. + * + * @{ + */ + +//! \name System Clock Initialization +//@{ +/** + * \fn void sysclk_init(void) + * \brief Initialize the synchronous clock system. + * + * This function will initialize the system clock and its source. This + * includes: + * - Mask all synchronous clocks except for any clocks which are + * essential for normal operation (for example internal memory + * clocks). + * - Set up the system clock prescalers as specified by the + * application's configuration file. + * - Enable the clock source specified by the application's + * configuration file (oscillator or PLL) and wait for it to become + * stable. + * - Set the main system clock source to the clock specified by the + * application's configuration file. + * + * Since all non-essential peripheral clocks are initially disabled, it + * is the responsibility of the peripheral driver to re-enable any + * clocks that are needed for normal operation. + */ +//@} + +//! @} + +#endif /* SYSCLK_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/common/services/clock/xmega/osc.h b/DSTAT-temp/src/asf/common/services/clock/xmega/osc.h new file mode 100644 index 0000000..bdb17fa --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/clock/xmega/osc.h @@ -0,0 +1,461 @@ +/** + * \file + * + * \brief Chip-specific oscillator management functions + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef XMEGA_OSC_H_INCLUDED +#define XMEGA_OSC_H_INCLUDED + +#include +#include + +/** + * \weakgroup osc_group + * + * \section osc_group_errata Errata + * - Auto-calibration does not work on XMEGA A1 revision H and + * earlier. + * @{ + */ + +//! \name Oscillator identifiers +//@{ +//! 2 MHz Internal RC Oscillator +#define OSC_ID_RC2MHZ OSC_RC2MEN_bm +//! 32 MHz Internal RC Oscillator +#define OSC_ID_RC32MHZ OSC_RC32MEN_bm +//! 32 KHz Internal RC Oscillator +#define OSC_ID_RC32KHZ OSC_RC32KEN_bm +//! External Oscillator +#define OSC_ID_XOSC OSC_XOSCEN_bm +/** + * \brief Reference from USB Start Of Frame + * \note This cannot be enabled or disabled, but can be used as a reference for + * the autocalibration (DFLL). + */ +#define OSC_ID_USBSOF 0xff +//@} + +//! \name External oscillator types +//@{ +#define XOSC_TYPE_EXTERNAL 0 //!< External clock signal +#define XOSC_TYPE_32KHZ 2 //!< 32.768 kHz resonator on TOSC +#define XOSC_TYPE_XTAL 3 //!< 0.4 to 16 MHz resonator on XTAL +//@} + +/** + * \def CONFIG_XOSC_32KHZ_LPM + * \brief Define for enabling Low Power Mode for 32 kHz external oscillator. + */ +#ifdef __DOXYGEN__ +# define CONFIG_XOSC_32KHZ_LPM +#endif /* __DOXYGEN__ */ + +/** + * \def CONFIG_XOSC_STARTUP + * \brief Board-dependent value that determines the number of start-up cycles + * for external resonators, based on BOARD_XOSC_STARTUP_US. This is written to + * the two MSB of the XOSCSEL field of OSC.XOSCCTRL. + * + * \note This is automatically computed from BOARD_XOSC_HZ and + * BOARD_XOSC_STARTUP_US if it is not manually set. + */ + +//! \name XTAL resonator start-up cycles +//@{ +#define XOSC_STARTUP_256 0 //!< 256 cycle start-up time +#define XOSC_STARTUP_1024 1 //!< 1 k cycle start-up time +#define XOSC_STARTUP_16384 2 //!< 16 k cycle start-up time +//@} + +/** + * \def CONFIG_XOSC_RANGE + * \brief Board-dependent value that sets the frequency range of the external + * oscillator. This is written to the FRQRANGE field of OSC.XOSCCTRL. + * + * \note This is automatically computed from BOARD_XOSC_HZ if it is not manually + * set. + */ + +//! \name XTAL resonator frequency range +//@{ +//! 0.4 to 2 MHz frequency range +#define XOSC_RANGE_04TO2 OSC_FRQRANGE_04TO2_gc +//! 2 to 9 MHz frequency range +#define XOSC_RANGE_2TO9 OSC_FRQRANGE_2TO9_gc +//! 9 to 12 MHz frequency range +#define XOSC_RANGE_9TO12 OSC_FRQRANGE_9TO12_gc +//! 12 to 16 MHz frequency range +#define XOSC_RANGE_12TO16 OSC_FRQRANGE_12TO16_gc +//@} + +/** + * \def XOSC_STARTUP_TIMEOUT + * \brief Number of us to wait for XOSC to start + * + * This is the number of slow clock cycles corresponding to + * OSC0_STARTUP_VALUE with an additional 25% safety margin. If the + * oscillator isn't running when this timeout has expired, it is assumed + * to have failed to start. + */ + +// If application intends to use XOSC. +#ifdef BOARD_XOSC_HZ +// Get start-up config for XOSC, if not manually set. +# ifndef CONFIG_XOSC_STARTUP +# ifndef BOARD_XOSC_STARTUP_US +# error BOARD_XOSC_STARTUP_US must be configured. +# else +//! \internal Number of start-up cycles for the board's XOSC. +# define BOARD_XOSC_STARTUP_CYCLES \ + (BOARD_XOSC_HZ / 1000000 * BOARD_XOSC_STARTUP_US) + +# if (BOARD_XOSC_TYPE == XOSC_TYPE_XTAL) +# if (BOARD_XOSC_STARTUP_CYCLES > 16384) +# error BOARD_XOSC_STARTUP_US is too high for current BOARD_XOSC_HZ. + +# elif (BOARD_XOSC_STARTUP_CYCLES > 1024) +# define CONFIG_XOSC_STARTUP XOSC_STARTUP_16384 +# define XOSC_STARTUP_TIMEOUT (16384*(1000000/BOARD_XOSC_HZ)) + +# elif (BOARD_XOSC_STARTUP_CYCLES > 256) +# define CONFIG_XOSC_STARTUP XOSC_STARTUP_1024 +# define XOSC_STARTUP_TIMEOUT (1024*(1000000/BOARD_XOSC_HZ)) + +# else +# define CONFIG_XOSC_STARTUP XOSC_STARTUP_256 +# define XOSC_STARTUP_TIMEOUT (256*(1000000/BOARD_XOSC_HZ)) +# endif +# else /* BOARD_XOSC_TYPE == XOSC_TYPE_XTAL */ +# define CONFIG_XOSC_STARTUP 0 +# endif +# endif /* BOARD_XOSC_STARTUP_US */ +# endif /* CONFIG_XOSC_STARTUP */ + +// Get frequency range setting for XOSC, if not manually set. +# ifndef CONFIG_XOSC_RANGE +# if (BOARD_XOSC_TYPE == XOSC_TYPE_XTAL) +# if (BOARD_XOSC_HZ < 400000) +# error BOARD_XOSC_HZ is below minimum frequency of 400 kHz. + +# elif (BOARD_XOSC_HZ < 2000000) +# define CONFIG_XOSC_RANGE XOSC_RANGE_04TO2 + +# elif (BOARD_XOSC_HZ < 9000000) +# define CONFIG_XOSC_RANGE XOSC_RANGE_2TO9 + +# elif (BOARD_XOSC_HZ < 12000000) +# define CONFIG_XOSC_RANGE XOSC_RANGE_9TO12 + +# elif (BOARD_XOSC_HZ <= 16000000) +# define CONFIG_XOSC_RANGE XOSC_RANGE_12TO16 + +# else +# error BOARD_XOSC_HZ is above maximum frequency of 16 MHz. +# endif +# else /* BOARD_XOSC_TYPE == XOSC_TYPE_XTAL */ +# define CONFIG_XOSC_RANGE 0 +# endif +# endif /* CONFIG_XOSC_RANGE */ +#endif /* BOARD_XOSC_HZ */ + +#ifndef __ASSEMBLY__ + +/** + * \internal + * \brief Enable internal oscillator \a id + * + * Do not call this function directly. Use osc_enable() instead. + */ +static inline void osc_enable_internal(uint8_t id) +{ + irqflags_t flags; + + Assert(id != OSC_ID_USBSOF); + + flags = cpu_irq_save(); + OSC.CTRL |= id; + cpu_irq_restore(flags); +} + +#if defined(BOARD_XOSC_HZ) || defined(__DOXYGEN__) + +/** + * \internal + * \brief Enable external oscillator \a id + * + * Do not call this function directly. Use osc_enable() instead. Also + * note that this function is only available if the board actually has + * an external oscillator crystal. + */ +static inline void osc_enable_external(uint8_t id) +{ + irqflags_t flags; + + Assert(id == OSC_ID_XOSC); + +#ifndef CONFIG_XOSC_32KHZ_LPM + OSC.XOSCCTRL = BOARD_XOSC_TYPE | (CONFIG_XOSC_STARTUP << 2) | + CONFIG_XOSC_RANGE; +#else + OSC.XOSCCTRL = BOARD_XOSC_TYPE | (CONFIG_XOSC_STARTUP << 2) | + CONFIG_XOSC_RANGE | OSC_X32KLPM_bm; +#endif /* CONFIG_XOSC_32KHZ_LPM */ + + flags = cpu_irq_save(); + OSC.CTRL |= id; + cpu_irq_restore(flags); +} +#else + +static inline void osc_enable_external(uint8_t id) +{ + Assert(false); // No external oscillator on the selected board +} +#endif + +static inline void osc_disable(uint8_t id) +{ + irqflags_t flags; + + Assert(id != OSC_ID_USBSOF); + + flags = cpu_irq_save(); + OSC.CTRL &= ~id; + cpu_irq_restore(flags); +} + +static inline void osc_enable(uint8_t id) +{ + if (id != OSC_ID_XOSC) { + osc_enable_internal(id); + } else { + osc_enable_external(id); + } +} + +static inline bool osc_is_ready(uint8_t id) +{ + Assert(id != OSC_ID_USBSOF); + + return OSC.STATUS & id; +} + +//! \name XMEGA-Specific Oscillator Features +//@{ + +/** + * \brief Enable DFLL-based automatic calibration of an internal + * oscillator. + * + * The XMEGA features two Digital Frequency Locked Loops (DFLLs) which + * can be used to improve the accuracy of the 2 MHz and 32 MHz internal + * RC oscillators. The DFLL compares the oscillator frequency with a + * more accurate reference clock to do automatic run-time calibration of + * the oscillator. + * + * This function enables auto-calibration for either the 2 MHz or 32 MHz + * internal oscillator using either the 32.768 kHz calibrated internal + * oscillator or an external crystal oscillator as a reference. If the + * latter option is used, the crystal must be connected to the TOSC pins + * and run at 32.768 kHz. + * + * \param id The ID of the oscillator for which to enable + * auto-calibration: + * \arg \c OSC_ID_RC2MHZ or \c OSC_ID_RC32MHZ. + * \param ref_id The ID of the oscillator to use as a reference: + * \arg \c OSC_ID_RC32KHZ or \c OSC_ID_XOSC for internal or external 32 kHz + * reference, respectively. + * \arg \c OSC_ID_USBSOF for 32 MHz only when USB is available and running. + */ +static inline void osc_enable_autocalibration(uint8_t id, uint8_t ref_id) +{ + irqflags_t flags; + + flags = cpu_irq_save(); + switch (id) { + case OSC_ID_RC2MHZ: + Assert((ref_id == OSC_ID_RC32KHZ) || (ref_id == OSC_ID_XOSC)); + + if (ref_id == OSC_ID_XOSC) { + osc_enable(OSC_ID_RC32KHZ); + OSC.DFLLCTRL |= OSC_RC2MCREF_bm; + } else { + OSC.DFLLCTRL &= ~(OSC_RC2MCREF_bm); + } + DFLLRC2M.CTRL |= DFLL_ENABLE_bm; + break; + + case OSC_ID_RC32MHZ: +#if XMEGA_AU || XMEGA_B || XMEGA_C + Assert((ref_id == OSC_ID_RC32KHZ) + || (ref_id == OSC_ID_XOSC) + || (ref_id == OSC_ID_USBSOF)); + + OSC.DFLLCTRL &= ~(OSC_RC32MCREF_gm); + + if (ref_id == OSC_ID_XOSC) { + osc_enable(OSC_ID_RC32KHZ); + OSC.DFLLCTRL |= OSC_RC32MCREF_XOSC32K_gc; + } + else if (ref_id == OSC_ID_RC32KHZ) { + OSC.DFLLCTRL |= OSC_RC32MCREF_RC32K_gc; + } + else if (ref_id == OSC_ID_USBSOF) { + /* + * Calibrate 32MRC at 48MHz using USB SOF + * 48MHz / 1kHz = 0xBB80 + */ + DFLLRC32M.COMP1 = 0x80; + DFLLRC32M.COMP2 = 0xBB; + OSC.DFLLCTRL |= OSC_RC32MCREF_USBSOF_gc; + } +#else + Assert((ref_id == OSC_ID_RC32KHZ) || + (ref_id == OSC_ID_XOSC)); + + if (ref_id == OSC_ID_XOSC) { + osc_enable(OSC_ID_RC32KHZ); + OSC.DFLLCTRL |= OSC_RC32MCREF_bm; + } + else if (ref_id == OSC_ID_RC32KHZ) { + OSC.DFLLCTRL &= ~(OSC_RC32MCREF_bm); + } +#endif + DFLLRC32M.CTRL |= DFLL_ENABLE_bm; + break; + + default: + Assert(false); + break; + } + cpu_irq_restore(flags); +} + +/** + * \brief Disable DFLL-based automatic calibration of an internal + * oscillator. + * + * \see osc_enable_autocalibration + * + * \param id The ID of the oscillator for which to disable + * auto-calibration: + * \arg \c OSC_ID_RC2MHZ or \c OSC_ID_RC32MHZ. + */ +static inline void osc_disable_autocalibration(uint8_t id) +{ + switch (id) { + case OSC_ID_RC2MHZ: + DFLLRC2M.CTRL = 0; + break; + + case OSC_ID_RC32MHZ: + DFLLRC32M.CTRL = 0; + break; + + default: + Assert(false); + break; + } +} + +/** + * \brief Load a specific calibration value for the specified oscillator. + * + * \param id The ID of the oscillator for which to disable + * auto-calibration: + * \arg \c OSC_ID_RC2MHZ or \c OSC_ID_RC32MHZ. + * \param calib The specific calibration value required: + * + */ +static inline void osc_user_calibration(uint8_t id, uint16_t calib) +{ + switch (id) { + case OSC_ID_RC2MHZ: + DFLLRC2M.CALA=LSB(calib); + DFLLRC2M.CALB=MSB(calib); + break; + + case OSC_ID_RC32MHZ: + DFLLRC32M.CALA=LSB(calib); + DFLLRC32M.CALB=MSB(calib); + break; + + default: + Assert(false); + break; + } +} +//@} + +static inline uint32_t osc_get_rate(uint8_t id) +{ + Assert(id != OSC_ID_USBSOF); + + switch (id) { + case OSC_ID_RC2MHZ: + return 2000000UL; + + case OSC_ID_RC32MHZ: +#ifdef CONFIG_OSC_RC32_CAL + return CONFIG_OSC_RC32_CAL; +#else + return 32000000UL; +#endif + + case OSC_ID_RC32KHZ: + return 32768UL; + +#ifdef BOARD_XOSC_HZ + case OSC_ID_XOSC: + return BOARD_XOSC_HZ; +#endif + + default: + Assert(false); + return 0; + } +} + +#endif /* __ASSEMBLY__ */ + +//! @} + +#endif /* XMEGA_OSC_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/common/services/clock/xmega/pll.h b/DSTAT-temp/src/asf/common/services/clock/xmega/pll.h new file mode 100644 index 0000000..0055b2b --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/clock/xmega/pll.h @@ -0,0 +1,262 @@ +/** + * \file + * + * \brief Chip-specific PLL management functions + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef XMEGA_PLL_H_INCLUDED +#define XMEGA_PLL_H_INCLUDED + +#include + +/** + * \weakgroup pll_group + * @{ + */ + +#define NR_PLLS 1 +#define PLL_MIN_HZ 10000000UL +#define PLL_MAX_HZ 200000000UL +#define PLL_NR_OPTIONS 0 + +enum pll_source { + //! 2 MHz Internal RC Oscillator + PLL_SRC_RC2MHZ = OSC_PLLSRC_RC2M_gc, + //! 32 MHz Internal RC Oscillator + PLL_SRC_RC32MHZ = OSC_PLLSRC_RC32M_gc, + //! External Clock Source + PLL_SRC_XOSC = OSC_PLLSRC_XOSC_gc, +}; + +#define pll_get_default_rate(pll_id) \ + pll_get_default_rate_priv(CONFIG_PLL##pll_id##_SOURCE, \ + CONFIG_PLL##pll_id##_MUL, \ + CONFIG_PLL##pll_id##_DIV) + +/** + * \internal + * \brief Return clock rate for specified PLL settings. + * + * \note Due to the hardware implementation of the PLL, \a div must be 4 if the + * 32 MHz RC oscillator is used as reference and 1 otherwise. The reference must + * be above 440 kHz, and the output between 10 and 200 MHz. + * + * \param src ID of the PLL's reference source oscillator. + * \param mul Multiplier for the PLL. + * \param div Divisor for the PLL. + * + * \retval Output clock rate from PLL. + */ +static inline uint32_t pll_get_default_rate_priv(enum pll_source src, + unsigned int mul, unsigned int div) +{ + uint32_t rate; + + switch (src) { + case PLL_SRC_RC2MHZ: + rate = 2000000UL; + Assert(div == 1); + break; + + case PLL_SRC_RC32MHZ: +#ifdef CONFIG_OSC_RC32_CAL //32MHz oscillator is calibrated to another frequency + rate = CONFIG_OSC_RC32_CAL / 4; +#else + rate = 8000000UL; + #endif + Assert(div == 4); + break; + + case PLL_SRC_XOSC: + rate = osc_get_rate(OSC_ID_XOSC); + Assert(div == 1); + break; + + default: + break; + } + + Assert(rate >= 440000UL); + + rate *= mul; + + Assert(rate >= PLL_MIN_HZ); + Assert(rate <= PLL_MAX_HZ); + + return rate; +} + +struct pll_config { + uint8_t ctrl; +}; + +/** + * \note The XMEGA PLL hardware uses hard-wired input dividers, so the + * user must ensure that \a div is set as follows: + * - If \a src is PLL_SRC_32MHZ, \a div must be set to 4. + * - Otherwise, \a div must be set to 1. + */ +static inline void pll_config_init(struct pll_config *cfg, enum pll_source src, + unsigned int div, unsigned int mul) +{ + Assert(mul >= 1 && mul <= 31); + + if (src == PLL_SRC_RC32MHZ) { + Assert(div == 4); + } else { + Assert(div == 1); + } + + /* Initialize the configuration */ + cfg->ctrl = src | (mul << OSC_PLLFAC_gp); +} + +#define pll_config_defaults(cfg, pll_id) \ + pll_config_init(cfg, \ + CONFIG_PLL##pll_id##_SOURCE, \ + CONFIG_PLL##pll_id##_DIV, \ + CONFIG_PLL##pll_id##_MUL) + +static inline void pll_config_read(struct pll_config *cfg, unsigned int pll_id) +{ + Assert(pll_id < NR_PLLS); + + cfg->ctrl = OSC.PLLCTRL; +} + +static inline void pll_config_write(const struct pll_config *cfg, + unsigned int pll_id) +{ + Assert(pll_id < NR_PLLS); + + OSC.PLLCTRL = cfg->ctrl; +} + +/** + * \note If a different PLL reference oscillator than those enabled by + * \ref sysclk_init() is used, the user must ensure that the desired reference + * is enabled prior to calling this function. + */ +static inline void pll_enable(const struct pll_config *cfg, + unsigned int pll_id) +{ + irqflags_t flags; + + Assert(pll_id < NR_PLLS); + + flags = cpu_irq_save(); + pll_config_write(cfg, pll_id); + OSC.CTRL |= OSC_PLLEN_bm; + cpu_irq_restore(flags); +} + +/*! \note This will not automatically disable the reference oscillator that is + * configured for the PLL. + */ +static inline void pll_disable(unsigned int pll_id) +{ + irqflags_t flags; + + Assert(pll_id < NR_PLLS); + + flags = cpu_irq_save(); + OSC.CTRL &= ~OSC_PLLEN_bm; + cpu_irq_restore(flags); +} + +static inline bool pll_is_locked(unsigned int pll_id) +{ + Assert(pll_id < NR_PLLS); + + return OSC.STATUS & OSC_PLLRDY_bm; +} + +static inline void pll_enable_source(enum pll_source src) +{ + switch (src) { + case PLL_SRC_RC2MHZ: + break; + + case PLL_SRC_RC32MHZ: + if (!osc_is_ready(OSC_ID_RC32MHZ)) { + osc_enable(OSC_ID_RC32MHZ); + osc_wait_ready(OSC_ID_RC32MHZ); + } + break; + + case PLL_SRC_XOSC: + if (!osc_is_ready(OSC_ID_XOSC)) { + osc_enable(OSC_ID_XOSC); + osc_wait_ready(OSC_ID_XOSC); + } + break; + default: + Assert(false); + break; + } +} + +static inline void pll_enable_config_defaults(unsigned int pll_id) +{ + struct pll_config pllcfg; + + if (pll_is_locked(pll_id)) { + return; // Pll already running + } + switch (pll_id) { +#ifdef CONFIG_PLL0_SOURCE + case 0: + pll_enable_source(CONFIG_PLL0_SOURCE); + pll_config_init(&pllcfg, + CONFIG_PLL0_SOURCE, + CONFIG_PLL0_DIV, + CONFIG_PLL0_MUL); + break; +#endif + default: + Assert(false); + break; + } + pll_enable(&pllcfg, pll_id); + while (!pll_is_locked(pll_id)); +} + +//! @} + +#endif /* XMEGA_PLL_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/common/services/clock/xmega/sysclk.c b/DSTAT-temp/src/asf/common/services/clock/xmega/sysclk.c new file mode 100644 index 0000000..db7b720 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/clock/xmega/sysclk.c @@ -0,0 +1,244 @@ +/** + * \file + * + * \brief Chip-specific system clock management functions + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#include + +#include +#include +#include + +#if XMEGA_AU || XMEGA_B || XMEGA_C +# include +#endif + + +void sysclk_init(void) +{ + uint8_t *reg = (uint8_t *)&PR.PRGEN; + uint8_t i; +#ifdef CONFIG_OSC_RC32_CAL + uint16_t cal; +#endif + bool need_rc2mhz = false; + + /* Turn off all peripheral clocks that can be turned off. */ + for (i = 0; i <= SYSCLK_PORT_F; i++) { + *(reg++) = 0xff; + } + + /* Set up system clock prescalers if different from defaults */ + if ((CONFIG_SYSCLK_PSADIV != SYSCLK_PSADIV_1) + || (CONFIG_SYSCLK_PSBCDIV != SYSCLK_PSBCDIV_1_1)) { + sysclk_set_prescalers(CONFIG_SYSCLK_PSADIV, + CONFIG_SYSCLK_PSBCDIV); + } +#if (CONFIG_OSC_RC32_CAL==48000000UL) + MSB(cal) = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(USBRCOSC)); + LSB(cal) = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(USBRCOSCA)); + /* + * If a device has an uncalibrated value in the + * production signature row (early sample part), load a + * sane default calibration value. + */ + if (cal == 0xFFFF) { + cal = 0x2340; + } + osc_user_calibration(OSC_ID_RC32MHZ,cal); +#endif + /* + * Switch to the selected initial system clock source, unless + * the default internal 2 MHz oscillator is selected. + */ + if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RC2MHZ) { + need_rc2mhz = true; + } else { + switch (CONFIG_SYSCLK_SOURCE) { + case SYSCLK_SRC_RC32MHZ: + osc_enable(OSC_ID_RC32MHZ); + osc_wait_ready(OSC_ID_RC32MHZ); +#ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC + if (CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC + != OSC_ID_USBSOF) { + osc_enable(CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC); + osc_wait_ready(CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC); + } + osc_enable_autocalibration(OSC_ID_RC32MHZ, + CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC); +#endif + break; + + case SYSCLK_SRC_RC32KHZ: + osc_enable(OSC_ID_RC32KHZ); + osc_wait_ready(OSC_ID_RC32KHZ); + break; + + case SYSCLK_SRC_XOSC: + osc_enable(OSC_ID_XOSC); + osc_wait_ready(OSC_ID_XOSC); + break; + +#ifdef CONFIG_PLL0_SOURCE + case SYSCLK_SRC_PLL: + if (CONFIG_PLL0_SOURCE == PLL_SRC_RC2MHZ) { + need_rc2mhz = true; + } + pll_enable_config_defaults(0); + break; +#endif + default: + //unhandled_case(CONFIG_SYSCLK_SOURCE); + return; + } + + ccp_write_io((uint8_t *)&CLK.CTRL, CONFIG_SYSCLK_SOURCE); + Assert(CLK.CTRL == CONFIG_SYSCLK_SOURCE); + } + + if (need_rc2mhz) { +#ifdef CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC + osc_enable(CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC); + osc_wait_ready(CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC); + osc_enable_autocalibration(OSC_ID_RC2MHZ, + CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC); +#endif + } else { + osc_disable(OSC_ID_RC2MHZ); + } + +#ifdef CONFIG_RTC_SOURCE + sysclk_rtcsrc_enable(CONFIG_RTC_SOURCE); +#endif +} + +void sysclk_enable_module(enum sysclk_port_id port, uint8_t id) +{ + irqflags_t flags = cpu_irq_save(); + + *((uint8_t *)&PR.PRGEN + port) &= ~id; + + cpu_irq_restore(flags); +} + +void sysclk_disable_module(enum sysclk_port_id port, uint8_t id) +{ + irqflags_t flags = cpu_irq_save(); + + *((uint8_t *)&PR.PRGEN + port) |= id; + + cpu_irq_restore(flags); +} + +#if XMEGA_AU || XMEGA_B || XMEGA_C || defined(__DOXYGEN__) + +/** + * \brief Enable clock for the USB module + * + * \pre CONFIG_USBCLK_SOURCE must be defined. + * + * \param frequency The required USB clock frequency in MHz: + * \arg \c 6 for 6 MHz + * \arg \c 48 for 48 MHz + */ +void sysclk_enable_usb(uint8_t frequency) +{ + uint8_t prescaler; + + Assert((frequency == 6) || (frequency == 48)); + + /* + * Enable or disable prescaler depending on if the USB frequency is 6 + * MHz or 48 MHz. Only 6 MHz USB frequency requires prescaling. + */ + if (frequency == 6) { + prescaler = CLK_USBPSDIV_8_gc; + } + else { + prescaler = 0; + } + + /* + * Switch to the system clock selected by the user. + */ + switch (CONFIG_USBCLK_SOURCE) { + case USBCLK_SRC_RCOSC: + if (!osc_is_ready(OSC_ID_RC32MHZ)) { + osc_enable(OSC_ID_RC32MHZ); + osc_wait_ready(OSC_ID_RC32MHZ); +#ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC + osc_enable_autocalibration(OSC_ID_RC32MHZ, + CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC); +#endif + } + ccp_write_io((uint8_t *)&CLK.USBCTRL, (prescaler) + | CLK_USBSRC_RC32M_gc + | CLK_USBSEN_bm); + break; + +#ifdef CONFIG_PLL0_SOURCE + case USBCLK_SRC_PLL: + pll_enable_config_defaults(0); + ccp_write_io((uint8_t *)&CLK.USBCTRL, (prescaler) + | CLK_USBSRC_PLL_gc + | CLK_USBSEN_bm); + break; +#endif + + default: + Assert(false); + break; + } + + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_USB); +} + +/** + * \brief Disable clock for the USB module + */ +void sysclk_disable_usb(void) +{ + sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_USB); + ccp_write_io((uint8_t *)&CLK.USBCTRL, 0); +} +#endif // XMEGA_AU || XMEGA_B || XMEGA_C diff --git a/DSTAT-temp/src/asf/common/services/clock/xmega/sysclk.h b/DSTAT-temp/src/asf/common/services/clock/xmega/sysclk.h new file mode 100644 index 0000000..6acd0d0 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/clock/xmega/sysclk.h @@ -0,0 +1,1393 @@ +/** + * \file + * + * \brief Chip-specific system clock management functions + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef XMEGA_SYSCLK_H_INCLUDED +#define XMEGA_SYSCLK_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +// Include clock configuration for the project. +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \page sysclk_quickstart Quick Start Guide for the System Clock Management service (XMEGA) + * + * This is the quick start guide for the \ref sysclk_group "System Clock Management" + * service, with step-by-step instructions on how to configure and use the service for + * specific use cases. + * + * \section sysclk_quickstart_usecases System Clock Management use cases + * - \ref sysclk_quickstart_basic + * - \ref sysclk_quickstart_use_case_2 + * - \ref sysclk_quickstart_use_case_3 + * + * \section sysclk_quickstart_basic Basic usage of the System Clock Management service + * This section will present a basic use case for the System Clock Management service. + * This use case will configure the main system clock to 32MHz, using an internal PLL + * module to multiply the frequency of a crystal attached to the microcontroller. The + * secondary peripheral bus clock and CPU clock are scaled down from the speed of the + * main system clock. + * + * \subsection sysclk_quickstart_use_case_1_prereq Prerequisites + * - None + * + * \subsection sysclk_quickstart_use_case_1_setup_steps Initialization code + * Add to the application initialization code: + * \code + * sysclk_init(); + * \endcode + * + * \subsection sysclk_quickstart_use_case_1_setup_steps_workflow Workflow + * -# Configure the system clocks according to the settings in conf_clock.h: + * \code sysclk_init(); \endcode + * + * \subsection sysclk_quickstart_use_case_1_example_code Example code + * Add or uncomment the following in your conf_clock.h header file, commenting out all other + * definitions of the same symbol(s): + * \code + * #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLL + * + * // Fpll0 = (Fclk * PLL_mul) / PLL_div + * #define CONFIG_PLL0_SOURCE PLL_SRC_XOSC + * #define CONFIG_PLL0_MUL (32000000UL / BOARD_XOSC_HZ) + * #define CONFIG_PLL0_DIV 1 + * + * // Fbus = Fsys / (2 ^ BUS_div) + * #define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_1 + * #define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_2 + * \endcode + * + * \subsection sysclk_quickstart_use_case_1_example_workflow Workflow + * -# Configure the main system clock to use the output of the PLL module as its source: + * \code #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLL \endcode + * -# Configure the PLL0 module to use external crystal oscillator XOSC as its source: + * \code #define CONFIG_PLL0_SOURCE PLL_SRC_XOSC \endcode + * -# Configure the PLL0 module to multiply the external oscillator XOSC frequency up to 32MHz: + * \code + * #define CONFIG_PLL0_MUL (32000000UL / BOARD_XOSC_HZ) + * #define CONFIG_PLL0_DIV 1 + * \endcode + * \note For user boards, \c BOARD_XOSC_HZ should be defined in the board \c conf_board.h configuration + * file as the frequency of the crystal attached to XOSC. + * -# Configure the main CPU clock and slow peripheral bus to run at 16MHz, run the fast peripheral bus + * at the full 32MHz speed: + * \code + * #define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_1 + * #define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_2 + * \endcode + * \note Some dividers are powers of two, while others are integer division factors. Refer to the + * formulas in the conf_clock.h template commented above each division define. + */ + +/** + * \page sysclk_quickstart_use_case_2 Advanced use case - Peripheral Bus Clock Management (XMEGA) + * + * \section sysclk_quickstart_use_case_2 Advanced use case - Peripheral Bus Clock Management + * This section will present a more advanced use case for the System Clock Management service. + * This use case will configure the main system clock to 32MHz, using an internal PLL + * module to multiply the frequency of a crystal attached to the microcontroller. The peripheral bus + * clocks will run at the same speed as the CPU clock, and the USB clock will be configured to use + * the internal 32MHz (nominal) RC oscillator calibrated to 48MHz with the USB Start-of-Frame as the + * calibration reference. + * + * \subsection sysclk_quickstart_use_case_2_prereq Prerequisites + * - None + * + * \subsection sysclk_quickstart_use_case_2_setup_steps Initialization code + * Add to the application initialization code: + * \code + * sysclk_init(); + * \endcode + * + * \subsection sysclk_quickstart_use_case_2_setup_steps_workflow Workflow + * -# Configure the system clocks according to the settings in conf_clock.h: + * \code sysclk_init(); \endcode + * + * \subsection sysclk_quickstart_use_case_2_example_code Example code + * Add or uncomment the following in your conf_clock.h header file, commenting out all other + * definitions of the same symbol(s): + * \code + * #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLL + * + * // Fpll0 = (Fclk * PLL_mul) / PLL_div + * #define CONFIG_PLL0_SOURCE PLL_SRC_XOSC + * #define CONFIG_PLL0_MUL (32000000UL / BOARD_XOSC_HZ) + * #define CONFIG_PLL0_DIV 1 + * + * // Fbus = Fsys / (2 ^ BUS_div) + * #define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_1 + * #define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_1 + * + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_RCOSC + * #define CONFIG_OSC_RC32_CAL 48000000UL + * #define CONFIG_OSC_AUTOCAL OSC_ID_RC32MHZ + * #define CONFIG_OSC_AUTOCAL_REF_OSC OSC_ID_USBSOF + * \endcode + * + * \subsection sysclk_quickstart_use_case_2_example_workflow Workflow + * -# Configure the main system clock to use the output of the PLL module as its source: + * \code #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLL \endcode + * -# Configure the PLL0 module to use external crystal oscillator XOSC as its source: + * \code #define CONFIG_PLL0_SOURCE PLL_SRC_XOSC \endcode + * -# Configure the PLL0 module to multiply the external oscillator XOSC frequency up to 32MHz: + * \code + * #define CONFIG_PLL0_MUL (32000000UL / BOARD_XOSC_HZ) + * #define CONFIG_PLL0_DIV 1 + * \endcode + * \note For user boards, \c BOARD_XOSC_HZ should be defined in the board \c conf_board.h configuration + * file as the frequency of the crystal attached to XOSC. + * -# Configure the main CPU and peripheral bus clocks to run at 32MHz: + * \code + * #define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_1 + * #define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_2 + * \endcode + * \note Some dividers are powers of two, while others are integer division factors. Refer to the + * formulas in the conf_clock.h template commented above each division define. + * -# Configure the USB module clock to use the internal fast (32MHz) RC oscillator: + * \code + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_RCOSC + * \endcode + * \note When the internal RC oscillator is used for the USB module, it must be recalibrated to 48MHz for + * the USB peripheral to function. If this oscillator is then used as the main system clock source, + * the clock must be divided down via the peripheral and CPU bus clock division constants to ensure + * that the maximum allowable CPU frequency is not exceeded. + * -# Configure the internal fast (32MHz) RC oscillator to calibrate to 48MHz using the USB Start of Frame (SOF) + * as the calibration reference: + * \code + * #define CONFIG_OSC_RC32_CAL 48000000UL + * #define CONFIG_OSC_AUTOCAL OSC_ID_RC32MHZ + * #define CONFIG_OSC_AUTOCAL_REF_OSC OSC_ID_USBSOF + * \endcode + */ + +/** + * \page sysclk_quickstart_use_case_3 Advanced use case - DFLL auto-calibration (XMEGA) + * + * \section sysclk_quickstart_use_case_3 Advanced use case - DFLL auto-calibration + * This section will present a more advanced use case for the System Clock + * Management service. This use case will configure the main system clock to + * 2MHz, using the internal 2MHz RC oscillator calibrated against the internal + * 32KHz oscillator. The peripheral bus clocks will run at the same speed as + * the CPU clock, and the USB clock will be configured to use the internal + * 32MHz (nominal) RC oscillator calibrated to 48MHz with the USB + * Start-of-Frame as the calibration reference. + * + * \subsection sysclk_quickstart_use_case_3_prereq Prerequisites + * - None + * + * \subsection sysclk_quickstart_use_case_3_setup_steps Initialization code + * Add to the application initialization code: + * \code + * sysclk_init(); + * \endcode + * + * \subsection sysclk_quickstart_use_case_3_setup_steps_workflow Workflow + * -# Configure the system clocks according to the settings in conf_clock.h: + * \code sysclk_init(); \endcode + * + * \subsection sysclk_quickstart_use_case_3_example_code Example code + * Add or uncomment the following in your conf_clock.h header file, + * commenting out all other definitions of the same symbol(s): + * \code + * #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC2MHZ + * + * #define CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC OSC_ID_RC32KHZ + * + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_RCOSC + * #define CONFIG_OSC_RC32_CAL 48000000UL + * #define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC OSC_ID_USBSOF + * \endcode + * + * \subsection sysclk_quickstart_use_case_3_example_workflow Workflow + * -# Configure the main system clock to use the internal 2MHz RC oscillator + * as its source: + * \code + * #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC2MHZ + * \endcode + * -# Configure the 2MHz DFLL auto-calibration to use the internal 32KHz RC + * oscillator: + * \code + * #define CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC OSC_ID_RC32KHZ + * \endcode + * \note For auto-calibration it's typically more relevant to use an external + * 32KHz crystal. So if that's the case use OSC_ID_XOSC instead. + * -# Configure the USB module clock to use the internal fast (32MHz) RC oscillator: + * \code + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_RCOSC + * \endcode + * -# Configure the internal fast (32MHz) RC oscillator to calibrate to 48MHz + * using the USB Start of Frame (SOF) as the calibration reference: + * \code + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_RCOSC + * #define CONFIG_OSC_RC32_CAL 48000000UL + * #define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC OSC_ID_USBSOF + * \endcode + */ + +/* Wrap old config into new one */ +#ifdef CONFIG_OSC_AUTOCAL +# if CONFIG_OSC_AUTOCAL == OSC_ID_RC2MHZ +# define CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC CONFIG_OSC_AUTOCAL_REF_OSC +# elif CONFIG_OSC_AUTOCAL == OSC_ID_RC32MHZ +# define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC CONFIG_OSC_AUTOCAL_REF_OSC +# else +# error Bad configuration of CONFIG_OSC_AUTOCAL and/or CONFIG_OSC_AUTOCAL_REF_OSC +# endif +#endif + +// Use 2 MHz with no prescaling if config was empty. +#ifndef CONFIG_SYSCLK_SOURCE +# define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC2MHZ +#endif /* CONFIG_SYSCLK_SOURCE */ + +#ifndef CONFIG_SYSCLK_PSADIV +# define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_1 +#endif /* CONFIG_SYSCLK_PSADIV */ + +#ifndef CONFIG_SYSCLK_PSBCDIV +# define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_1 +#endif /* CONFIG_SYSCLK_PSBCDIV */ + +/** + * \weakgroup sysclk_group + * + * \section sysclk_group_config Configuration Symbols + * + * The following configuration symbols may be used to specify the + * initial system clock configuration. If any of the symbols are not + * set, reasonable defaults will be provided. + * - \b CONFIG_SYSCLK_SOURCE: The initial system clock source. + * - \b CONFIG_SYSCLK_PSADIV: The initial Prescaler A setting. + * - \b CONFIG_SYSCLK_PSBCDIV: The initial Prescaler B setting. + * - \b CONFIG_USBCLK_SOURCE: The initial USB clock source. + * + * @{ + */ + +//! \name System Clock Sources +//@{ +//! Internal 2 MHz RC oscillator +#define SYSCLK_SRC_RC2MHZ CLK_SCLKSEL_RC2M_gc +//! Internal 32 MHz RC oscillator +#define SYSCLK_SRC_RC32MHZ CLK_SCLKSEL_RC32M_gc +//! Internal 32 KHz RC oscillator +#define SYSCLK_SRC_RC32KHZ CLK_SCLKSEL_RC32K_gc +//! External oscillator +#define SYSCLK_SRC_XOSC CLK_SCLKSEL_XOSC_gc +//! Phase-Locked Loop +#define SYSCLK_SRC_PLL CLK_SCLKSEL_PLL_gc +//@} + +//! \name Prescaler A Setting (relative to CLKsys) +//@{ +#define SYSCLK_PSADIV_1 CLK_PSADIV_1_gc //!< Do not prescale +#define SYSCLK_PSADIV_2 CLK_PSADIV_2_gc //!< Prescale CLKper4 by 2 +#define SYSCLK_PSADIV_4 CLK_PSADIV_4_gc //!< Prescale CLKper4 by 4 +#define SYSCLK_PSADIV_8 CLK_PSADIV_8_gc //!< Prescale CLKper4 by 8 +#define SYSCLK_PSADIV_16 CLK_PSADIV_16_gc //!< Prescale CLKper4 by 16 +#define SYSCLK_PSADIV_32 CLK_PSADIV_32_gc //!< Prescale CLKper4 by 32 +#define SYSCLK_PSADIV_64 CLK_PSADIV_64_gc //!< Prescale CLKper4 by 64 +#define SYSCLK_PSADIV_128 CLK_PSADIV_128_gc //!< Prescale CLKper4 by 128 +#define SYSCLK_PSADIV_256 CLK_PSADIV_256_gc //!< Prescale CLKper4 by 256 +#define SYSCLK_PSADIV_512 CLK_PSADIV_512_gc //!< Prescale CLKper4 by 512 +//@} + +//! \name Prescaler B and C Setting (relative to CLKper4) +//@{ +//! Do not prescale +#define SYSCLK_PSBCDIV_1_1 CLK_PSBCDIV_1_1_gc +//! Prescale CLKper and CLKcpu by 2 +#define SYSCLK_PSBCDIV_1_2 CLK_PSBCDIV_1_2_gc +//! Prescale CLKper2, CLKper and CLKcpu by 4 +#define SYSCLK_PSBCDIV_4_1 CLK_PSBCDIV_4_1_gc +//! Prescale CLKper2 by 2, CLKper and CLKcpu by 4 +#define SYSCLK_PSBCDIV_2_2 CLK_PSBCDIV_2_2_gc +//@} + +//! \name System Clock Port Numbers +enum sysclk_port_id { + SYSCLK_PORT_GEN, //!< Devices not associated with a specific port. + SYSCLK_PORT_A, //!< Devices on PORTA + SYSCLK_PORT_B, //!< Devices on PORTB + SYSCLK_PORT_C, //!< Devices on PORTC + SYSCLK_PORT_D, //!< Devices on PORTD + SYSCLK_PORT_E, //!< Devices on PORTE + SYSCLK_PORT_F, //!< Devices on PORTF +}; + +/*! \name Clocks not associated with any port + * + * \note See the datasheet for available modules in the device. + */ +//@{ +#define SYSCLK_DMA PR_DMA_bm //!< DMA Controller +#define SYSCLK_EVSYS PR_EVSYS_bm //!< Event System +#define SYSCLK_RTC PR_RTC_bm //!< Real-Time Counter +#define SYSCLK_EBI PR_EBI_bm //!< Ext Bus Interface +#define SYSCLK_AES PR_AES_bm //!< AES Module +#define SYSCLK_USB PR_USB_bm //!< USB Module +//@} + +/*! \name Clocks on PORTA and PORTB + * + * \note See the datasheet for available modules in the device. + */ +//@{ +#define SYSCLK_AC PR_AC_bm //!< Analog Comparator +#define SYSCLK_ADC PR_ADC_bm //!< A/D Converter +#define SYSCLK_DAC PR_DAC_bm //!< D/A Converter +//@} + +/*! \name Clocks on PORTC, PORTD, PORTE and PORTF + * + * \note See the datasheet for available modules in the device. + */ +//@{ +#define SYSCLK_TC0 PR_TC0_bm //!< Timer/Counter 0 +#define SYSCLK_TC1 PR_TC1_bm //!< Timer/Counter 1 +#define SYSCLK_HIRES PR_HIRES_bm //!< Hi-Res Extension +#define SYSCLK_SPI PR_SPI_bm //!< SPI controller +#define SYSCLK_USART0 PR_USART0_bm //!< USART 0 +#define SYSCLK_USART1 PR_USART1_bm //!< USART 1 +#define SYSCLK_TWI PR_TWI_bm //!< TWI controller +//@} + +/** + * \name RTC clock source identifiers + * + * @{ + */ + +/** 1kHz from internal ULP oscillator. Low precision */ +#define SYSCLK_RTCSRC_ULP CLK_RTCSRC_ULP_gc +/** 1.024kHz from 32.768kHz crystal oscillator TOSC */ +#define SYSCLK_RTCSRC_TOSC CLK_RTCSRC_TOSC_gc +/** 1.024kHz from 32.768kHz internal RC oscillator */ +#define SYSCLK_RTCSRC_RCOSC CLK_RTCSRC_RCOSC_gc +/** 32.768kHz from crystal oscillator TOSC */ +#define SYSCLK_RTCSRC_TOSC32 CLK_RTCSRC_TOSC32_gc +/** 32.768kHz from internal RC oscillator */ +#define SYSCLK_RTCSRC_RCOSC32 CLK_RTCSRC_RCOSC32_gc +/** External clock on TOSC1 */ +#define SYSCLK_RTCSRC_EXTCLK CLK_RTCSRC_EXTCLK_gc + +/** @} */ + +#if XMEGA_AU || XMEGA_B || XMEGA_C +//! \name USB Clock Sources +//@{ +//! Internal 32 MHz RC oscillator +#define USBCLK_SRC_RCOSC 0 +//! Phase-Locked Loop +#define USBCLK_SRC_PLL 1 +//@} + +/** + * \def CONFIG_USBCLK_SOURCE + * \brief Configuration symbol for the USB clock source + * + * If the device features an USB module, and this is intended to be used, this + * symbol must be defined with the clock source configuration. + * + * Define this as one of the \c USBCLK_SRC_xxx definitions. If the PLL is + * selected, it must be configured to run at 48 MHz. If the 32 MHz RC oscillator + * is selected, it must be tuned to 48 MHz by means of the DFLL. + */ +#ifdef __DOXYGEN__ +# define CONFIG_USBCLK_SOURCE +#endif + +#endif // XMEGA_AU || XMEGA_B || XMEGA_C + +#ifndef __ASSEMBLY__ + +/** + * \name Querying the system clock and its derived clocks + */ +//@{ + +/** + * \brief Return the current rate in Hz of the main system clock + * + * \todo This function assumes that the main clock source never changes + * once it's been set up, and that PLL0 always runs at the compile-time + * configured default rate. While this is probably the most common + * configuration, which we want to support as a special case for + * performance reasons, we will at some point need to support more + * dynamic setups as well. + * + * \return Frequency of the main system clock, in Hz. + */ +static inline uint32_t sysclk_get_main_hz(void) +{ + switch (CONFIG_SYSCLK_SOURCE) { + case SYSCLK_SRC_RC2MHZ: + return 2000000UL; + + case SYSCLK_SRC_RC32MHZ: +#ifdef CONFIG_OSC_RC32_CAL + return CONFIG_OSC_RC32_CAL; +#else + return 32000000UL; +#endif + + case SYSCLK_SRC_RC32KHZ: + return 32768UL; + +#ifdef BOARD_XOSC_HZ + case SYSCLK_SRC_XOSC: + return BOARD_XOSC_HZ; +#endif + +#ifdef CONFIG_PLL0_SOURCE + case SYSCLK_SRC_PLL: + return pll_get_default_rate(0); +#endif + + default: + //unhandled_case(CONFIG_SYSCLK_SOURCE); + return 0; + } +} + +/** + * \brief Return the current rate in Hz of clk_PER4. + * + * This clock can run up to four times faster than the CPU clock. + * + * \return Frequency of the clk_PER4 clock, in Hz. + */ +static inline uint32_t sysclk_get_per4_hz(void) +{ + uint8_t shift = 0; + + if (CONFIG_SYSCLK_PSADIV & (1U << CLK_PSADIV_gp)) { + shift = (CONFIG_SYSCLK_PSADIV >> (1 + CLK_PSADIV_gp)) + 1; + } + + return sysclk_get_main_hz() >> shift; +} + +/** + * \brief Return the current rate in Hz of clk_PER2. + * + * This clock can run up to two times faster than the CPU clock. + * + * \return Frequency of the clk_PER2 clock, in Hz. + */ +static inline uint32_t sysclk_get_per2_hz(void) +{ + switch (CONFIG_SYSCLK_PSBCDIV) { + case SYSCLK_PSBCDIV_1_1: /* Fall through */ + case SYSCLK_PSBCDIV_1_2: + return sysclk_get_per4_hz(); + + case SYSCLK_PSBCDIV_4_1: + return sysclk_get_per4_hz() / 4; + + case SYSCLK_PSBCDIV_2_2: + return sysclk_get_per4_hz() / 2; + + default: + //unhandled_case(CONFIG_SYSCLK_PSBCDIV); + return 0; + } +} + +/** + * \brief Return the current rate in Hz of clk_PER. + * + * This clock always runs at the same rate as the CPU clock unless the divider + * is set. + * + * \return Frequency of the clk_PER clock, in Hz. + */ +static inline uint32_t sysclk_get_per_hz(void) +{ + if (CONFIG_SYSCLK_PSBCDIV & (1U << CLK_PSBCDIV_gp)) + return sysclk_get_per2_hz() / 2; + else + return sysclk_get_per2_hz(); +} + +/** + * \brief Return the current rate in Hz of the CPU clock. + * + * \return Frequency of the CPU clock, in Hz. + */ +static inline uint32_t sysclk_get_cpu_hz(void) +{ + return sysclk_get_per_hz(); +} + +/** + * \brief Retrieves the current rate in Hz of the Peripheral Bus clock attached + * to the specified peripheral. + * + * \param module Pointer to the module's base address. + * + * \return Frequency of the bus attached to the specified peripheral, in Hz. + */ +static inline uint32_t sysclk_get_peripheral_bus_hz(const volatile void *module) +{ + if (module == NULL) { + Assert(false); + return 0; + } +#ifdef AES + else if (module == &AES) { + return sysclk_get_per_hz(); + } +#endif +#ifdef EBI + else if (module == &EBI) { + return sysclk_get_per2_hz(); + } +#endif +#ifdef RTC + else if (module == &RTC) { + return sysclk_get_per_hz(); + } +#endif +#ifdef EVSYS + else if (module == &EVSYS) { + return sysclk_get_per_hz(); + } +#endif +#ifdef DMA + else if (module == &DMA) { + return sysclk_get_per_hz(); + } +#endif +#ifdef ACA + else if (module == &ACA) { + return sysclk_get_per_hz(); + } +#endif +#ifdef ACB + else if (module == &ACB) { + return sysclk_get_per_hz(); + } +#endif +#ifdef ADCA + else if (module == &ADCA) { + return sysclk_get_per_hz(); + } +#endif +#ifdef ADCB + else if (module == &ADCB) { + return sysclk_get_per_hz(); + } +#endif +#ifdef DACA + else if (module == &DACA) { + return sysclk_get_per_hz(); + } +#endif +// Workaround for bad XMEGA D header file +#if !XMEGA_D +#ifdef DACB + else if (module == &DACB) { + return sysclk_get_per_hz(); + } +#endif +#endif // Workaround end +#ifdef TCC0 + else if (module == &TCC0) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TCD0 + else if (module == &TCD0) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TCE0 + else if (module == &TCE0) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TCF0 + else if (module == &TCF0) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TCC1 + else if (module == &TCC1) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TCD1 + else if (module == &TCD1) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TCE1 + else if (module == &TCE1) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TCF1 + else if (module == &TCF1) { + return sysclk_get_per_hz(); + } +#endif +#ifdef HIRESC + else if (module == &HIRESC) { + return sysclk_get_per4_hz(); + } +#endif +#ifdef HIRESD + else if (module == &HIRESD) { + return sysclk_get_per4_hz(); + } +#endif +#ifdef HIRESE + else if (module == &HIRESE) { + return sysclk_get_per4_hz(); + } +#endif +#ifdef HIRESF + else if (module == &HIRESF) { + return sysclk_get_per4_hz(); + } +#endif +#ifdef SPIC + else if (module == &SPIC) { + return sysclk_get_per_hz(); + } +#endif +#ifdef SPID + else if (module == &SPID) { + return sysclk_get_per_hz(); + } +#endif +#ifdef SPIE + else if (module == &SPIE) { + return sysclk_get_per_hz(); + } +#endif +#ifdef SPIF + else if (module == &SPIF) { + return sysclk_get_per_hz(); + } +#endif +#ifdef USARTC0 + else if (module == &USARTC0) { + return sysclk_get_per_hz(); + } +#endif +#ifdef USARTD0 + else if (module == &USARTD0) { + return sysclk_get_per_hz(); + } +#endif +#ifdef USARTE0 + else if (module == &USARTE0) { + return sysclk_get_per_hz(); + } +#endif +#ifdef USARTF0 + else if (module == &USARTF0) { + return sysclk_get_per_hz(); + } +#endif +#ifdef USARTC1 + else if (module == &USARTC1) { + return sysclk_get_per_hz(); + } +#endif +#ifdef USARTD1 + else if (module == &USARTD1) { + return sysclk_get_per_hz(); + } +#endif +#ifdef USARTE1 + else if (module == &USARTE1) { + return sysclk_get_per_hz(); + } +#endif +#ifdef USARTF1 + else if (module == &USARTF1) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TWIC + else if (module == &TWIC) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TWID + else if (module == &TWID) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TWIE + else if (module == &TWIE) { + return sysclk_get_per_hz(); + } +#endif +#ifdef TWIF + else if (module == &TWIF) { + return sysclk_get_per_hz(); + } +#endif + else { + Assert(false); + return 0; + } +} + +//@} + +//! \name Enabling and disabling synchronous clocks +//@{ + +/** + * \brief Enable the clock to peripheral \a id on port \a port + * + * \param port ID of the port to which the module is connected (one of + * the \c SYSCLK_PORT_* definitions). + * \param id The ID (bitmask) of the peripheral module to be enabled. + */ +extern void sysclk_enable_module(enum sysclk_port_id port, uint8_t id); + +/** + * \brief Disable the clock to peripheral \a id on port \a port + * + * \param port ID of the port to which the module is connected (one of + * the \c SYSCLK_PORT_* definitions). + * \param id The ID (bitmask) of the peripheral module to be disabled. + */ +extern void sysclk_disable_module(enum sysclk_port_id port, uint8_t id); + +/** + * \brief Enable a peripheral's clock from its base address. + * + * Enables the clock to a peripheral, given its base address. If the peripheral + * has an associated clock on the HSB bus, this will be enabled also. + * + * \param module Pointer to the module's base address. + */ +static inline void sysclk_enable_peripheral_clock(const volatile void *module) +{ + if (module == NULL) { + Assert(false); + } +#ifdef AES + else if (module == &AES) { + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_AES); + } +#endif +#ifdef EBI + else if (module == &EBI) { + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EBI); + } +#endif +#ifdef RTC + else if (module == &RTC) { + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_RTC); + } +#endif +#ifdef EVSYS + else if (module == &EVSYS) { + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS); + } +#endif +#ifdef DMA + else if (module == &DMA) { + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_DMA); + } +#endif +#ifdef ACA + else if (module == &ACA) { + sysclk_enable_module(SYSCLK_PORT_A, SYSCLK_AC); + } +#endif +#ifdef ACB + else if (module == &ACB) { + sysclk_enable_module(SYSCLK_PORT_B, SYSCLK_AC); + } +#endif +#ifdef ADCA + else if (module == &ADCA) { + sysclk_enable_module(SYSCLK_PORT_A, SYSCLK_ADC); + } +#endif +#ifdef ADCB + else if (module == &ADCB) { + sysclk_enable_module(SYSCLK_PORT_B, SYSCLK_ADC); + } +#endif +#ifdef DACA + else if (module == &DACA) { + sysclk_enable_module(SYSCLK_PORT_A, SYSCLK_DAC); + } +#endif +// Workaround for bad XMEGA D header file +#if !XMEGA_D +#ifdef DACB + else if (module == &DACB) { + sysclk_enable_module(SYSCLK_PORT_B, SYSCLK_DAC); + } +#endif +#endif // Workaround end +#ifdef TCC0 + else if (module == &TCC0) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC0); + } +#endif +#ifdef TCD0 + else if (module == &TCD0) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_TC0); + } +#endif +#ifdef TCE0 + else if (module == &TCE0) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_TC0); + } +#endif +#ifdef TCF0 + else if (module == &TCF0) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_TC0); + } +#endif +#ifdef TCC1 + else if (module == &TCC1) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC1); + } +#endif +#ifdef TCD1 + else if (module == &TCD1) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_TC1); + } +#endif +#ifdef TCE1 + else if (module == &TCE1) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_TC1); + } +#endif +#ifdef TCF1 + else if (module == &TCF1) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_TC1); + } +#endif +#ifdef HIRESC + else if (module == &HIRESC) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_HIRES); + } +#endif +#ifdef HIRESD + else if (module == &HIRESD) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_HIRES); + } +#endif +#ifdef HIRESE + else if (module == &HIRESE) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_HIRES); + } +#endif +#ifdef HIRESF + else if (module == &HIRESF) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_HIRES); + } +#endif +#ifdef SPIC + else if (module == &SPIC) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_SPI); + } +#endif +#ifdef SPID + else if (module == &SPID) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_SPI); + } +#endif +#ifdef SPIE + else if (module == &SPIE) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_SPI); + } +#endif +#ifdef SPIF + else if (module == &SPIF) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_SPI); + } +#endif +#ifdef USARTC0 + else if (module == &USARTC0) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_USART0); + } +#endif +#ifdef USARTD0 + else if (module == &USARTD0) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_USART0); + } +#endif +#ifdef USARTE0 + else if (module == &USARTE0) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_USART0); + } +#endif +#ifdef USARTF0 + else if (module == &USARTF0) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_USART0); + } +#endif +#ifdef USARTC1 + else if (module == &USARTC1) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_USART1); + } +#endif +#ifdef USARTD1 + else if (module == &USARTD1) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_USART1); + } +#endif +#ifdef USARTE1 + else if (module == &USARTE1) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_USART1); + } +#endif +#ifdef USARTF1 + else if (module == &USARTF1) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_USART1); + } +#endif +#ifdef TWIC + else if (module == &TWIC) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TWI); + } +#endif +#ifdef TWID + else if (module == &TWID) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_TWI); + } +#endif +#ifdef TWIE + else if (module == &TWIE) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_TWI); + } +#endif +#ifdef TWIF + else if (module == &TWIF) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_TWI); + } +#endif + else { + Assert(false); + } +} + +/** + * \brief Disable a peripheral's clock from its base address. + * + * Disables the clock to a peripheral, given its base address. If the peripheral + * has an associated clock on the HSB bus, this will be disabled also. + * + * \param module Pointer to the module's base address. + */ +static inline void sysclk_disable_peripheral_clock(const volatile void *module) +{ + if (module == NULL) { + Assert(false); + } +#ifdef AES + else if (module == &AES) { + sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_AES); + } +#endif +#ifdef EBI + else if (module == &EBI) { + sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_EBI); + } +#endif +#ifdef RTC + else if (module == &RTC) { + sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_RTC); + } +#endif +#ifdef EVSYS + else if (module == &EVSYS) { + sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS); + } +#endif +#ifdef DMA + else if (module == &DMA) { + sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_DMA); + } +#endif +#ifdef ACA + else if (module == &ACA) { + sysclk_disable_module(SYSCLK_PORT_A, SYSCLK_AC); + } +#endif +#ifdef ACB + else if (module == &ACB) { + sysclk_disable_module(SYSCLK_PORT_B, SYSCLK_AC); + } +#endif +#ifdef ADCA + else if (module == &ADCA) { + sysclk_disable_module(SYSCLK_PORT_A, SYSCLK_ADC); + } +#endif +#ifdef ADCB + else if (module == &ADCB) { + sysclk_disable_module(SYSCLK_PORT_B, SYSCLK_ADC); + } +#endif +#ifdef DACA + else if (module == &DACA) { + sysclk_disable_module(SYSCLK_PORT_A, SYSCLK_DAC); + } +#endif +// Workaround for bad XMEGA D header file +#if !XMEGA_D +#ifdef DACB + else if (module == &DACB) { + sysclk_disable_module(SYSCLK_PORT_B, SYSCLK_DAC); + } +#endif +#endif // Workaround end +#ifdef TCC0 + else if (module == &TCC0) { + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_TC0); + } +#endif +#ifdef TCD0 + else if (module == &TCD0) { + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_TC0); + } +#endif +#ifdef TCE0 + else if (module == &TCE0) { + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_TC0); + } +#endif +#ifdef TCF0 + else if (module == &TCF0) { + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_TC0); + } +#endif +#ifdef TCC1 + else if (module == &TCC1) { + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_TC1); + } +#endif +#ifdef TCD1 + else if (module == &TCD1) { + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_TC1); + } +#endif +#ifdef TCE1 + else if (module == &TCE1) { + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_TC1); + } +#endif +#ifdef TCF1 + else if (module == &TCF1) { + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_TC1); + } +#endif +#ifdef HIRESC + else if (module == &HIRESC) { + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_HIRES); + } +#endif +#ifdef HIRESD + else if (module == &HIRESD) { + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_HIRES); + } +#endif +#ifdef HIRESE + else if (module == &HIRESE) { + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_HIRES); + } +#endif +#ifdef HIRESF + else if (module == &HIRESF) { + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_HIRES); + } +#endif +#ifdef SPIC + else if (module == &SPIC) { + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_SPI); + } +#endif +#ifdef SPID + else if (module == &SPID) { + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_SPI); + } +#endif +#ifdef SPIE + else if (module == &SPIE) { + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_SPI); + } +#endif +#ifdef SPIF + else if (module == &SPIF) { + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_SPI); + } +#endif +#ifdef USARTC0 + else if (module == &USARTC0) { + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_USART0); + } +#endif +#ifdef USARTD0 + else if (module == &USARTD0) { + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_USART0); + } +#endif +#ifdef USARTE0 + else if (module == &USARTE0) { + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_USART0); + } +#endif +#ifdef USARTF0 + else if (module == &USARTF0) { + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_USART0); + } +#endif +#ifdef USARTC1 + else if (module == &USARTC1) { + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_USART1); + } +#endif +#ifdef USARTD1 + else if (module == &USARTD1) { + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_USART1); + } +#endif +#ifdef USARTE1 + else if (module == &USARTE1) { + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_USART1); + } +#endif +#ifdef USARTF1 + else if (module == &USARTF1) { + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_USART1); + } +#endif +#ifdef TWIC + else if (module == &TWIC) { + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_TWI); + } +#endif +#ifdef TWID + else if (module == &TWID) { + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_TWI); + } +#endif +#ifdef TWIE + else if (module == &TWIE) { + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_TWI); + } +#endif +#ifdef TWIF + else if (module == &TWIF) { + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_TWI); + } +#endif + else { + Assert(false); + } +} + +/** + * \brief Check if the synchronous clock is enabled for a module + * + * \param port ID of the port to which the module is connected (one of + * the \c SYSCLK_PORT_* definitions). + * \param id The ID (bitmask) of the peripheral module to check (one of + * the \c SYSCLK_* module definitions). + * + * \retval true If the clock for module \a id on \a port is enabled. + * \retval false If the clock for module \a id on \a port is disabled. + */ +static inline bool sysclk_module_is_enabled(enum sysclk_port_id port, + uint8_t id) +{ + uint8_t mask = *((uint8_t *)&PR.PRGEN + port); + return (mask & id) == 0; +} + +#if XMEGA_AU || XMEGA_B || XMEGA_C || defined(__DOXYGEN__) +# if defined(CONFIG_USBCLK_SOURCE) || defined(__DOXYGEN__) +# if (CONFIG_USBCLK_SOURCE == USBCLK_SRC_RCOSC) +# define USBCLK_STARTUP_TIMEOUT 1 +# elif (CONFIG_USBCLK_SOURCE == USBCLK_SRC_PLL) +# if (CONFIG_PLL0_SOURCE == PLL_SRC_XOSC) +# define USBCLK_STARTUP_TIMEOUT XOSC_STARTUP_TIMEOUT +# elif (CONFIG_PLL0_SOURCE == PLL_SRC_RC32MHZ) +# define USBCLK_STARTUP_TIMEOUT 1 +# elif (CONFIG_PLL0_SOURCE == PLL_SRC_RC2MHZ) +# define USBCLK_STARTUP_TIMEOUT 1 +# else +# error Unknow value for CONFIG_PLL0_SOURCE, see conf_clock.h. +# endif +# endif +# else /* CONFIG_USBCLK_SOURCE not defined */ +# define CONFIG_USBCLK_SOURCE USBCLK_SRC_RCOSC +# define USBCLK_STARTUP_TIMEOUT 1 +# endif /* CONFIG_USBCLK_SOURCE */ +void sysclk_enable_usb(uint8_t frequency); +void sysclk_disable_usb(void); +#endif /* XMEGA_AU || XMEGA_B || XMEGA_C */ +//@} + +//! \name System Clock Source and Prescaler configuration +//@{ + +/** + * \brief Set system clock prescaler configuration + * + * This function will change the system clock prescaler configuration to + * match the parameters. + * + * \note The parameters to this function are device-specific. + * + * \param psadiv The prescaler A setting (one of the \c SYSCLK_PSADIV_* + * definitions). This determines the clkPER4 frequency. + * \param psbcdiv The prescaler B and C settings (one of the \c SYSCLK_PSBCDIV_* + * definitions). These determine the clkPER2, clkPER and clkCPU frequencies. + */ +static inline void sysclk_set_prescalers(uint8_t psadiv, uint8_t psbcdiv) +{ + ccp_write_io((uint8_t *)&CLK.PSCTRL, psadiv | psbcdiv); +} + +/** + * \brief Change the source of the main system clock. + * + * \param src The new system clock source. Must be one of the constants + * from the System Clock Sources section. + */ +static inline void sysclk_set_source(uint8_t src) +{ + ccp_write_io((uint8_t *)&CLK.CTRL, src); +} + +/** + * \brief Lock the system clock configuration + * + * This function will lock the current system clock source and prescaler + * configuration, preventing any further changes. + */ +static inline void sysclk_lock(void) +{ + ccp_write_io((uint8_t *)&CLK.LOCK, CLK_LOCK_bm); +} + +//@} + +/** + * \name RTC clock source control + * @{ + */ + +/** + * \brief Enable RTC clock with specified clock source + * + * \param id RTC clock source ID. Select from SYSCLK_RTCSRC_ULP, + * SYSCLK_RTCSRC_RCOSC, SYSCLK_RTCSRC_TOSC, SYSCLK_RTCSRC_RCOSC32, + * SYSCLK_RTCSRC_TOSC32 or SYSCLK_RTCSRC_EXTCLK + */ +static inline void sysclk_rtcsrc_enable(uint8_t id) +{ + Assert((id & ~CLK_RTCSRC_gm) == 0); + + switch (id) { + case SYSCLK_RTCSRC_RCOSC: +#if !XMEGA_A && !XMEGA_D + case SYSCLK_RTCSRC_RCOSC32: +#endif + osc_enable(OSC_ID_RC32KHZ); + osc_wait_ready(OSC_ID_RC32KHZ); + break; + case SYSCLK_RTCSRC_TOSC: + case SYSCLK_RTCSRC_TOSC32: +#if !XMEGA_A && !XMEGA_D + case SYSCLK_RTCSRC_EXTCLK: +#endif + osc_enable(OSC_ID_XOSC); + osc_wait_ready(OSC_ID_XOSC); + break; + } + + CLK.RTCCTRL = id | CLK_RTCEN_bm; +} + +/** + * \brief Disable RTC clock + */ +static inline void sysclk_rtcsrc_disable(void) +{ + CLK.RTCCTRL = 0; +} + +/** @} */ + +//! \name System Clock Initialization +//@{ + +extern void sysclk_init(void); + +//@} + +#endif /* !__ASSEMBLY__ */ + +//! @} + +#ifdef __cplusplus +} +#endif + +#endif /* XMEGA_SYSCLK_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/common/services/delay/delay.h b/DSTAT-temp/src/asf/common/services/delay/delay.h new file mode 100644 index 0000000..a681ca8 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/delay/delay.h @@ -0,0 +1,137 @@ +/** + * \file + * + * \brief Common Delay Service + * + * Copyright (c) 2011 - 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef _DELAY_H_ +#define _DELAY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include + +#if UC3 +# include +#elif XMEGA +# include "xmega/cycle_counter.h" +#elif SAM +# include "sam/cycle_counter.h" +#endif + + +/** + * @defgroup group_common_services_delay Busy-Wait Delay Routines + * + * This module provides simple loop-based delay routines for those + * applications requiring a brief wait during execution. Common API + * for UC3, XMEGA, and AVR MEGA. + * + * @{ + */ + +/** + * @def F_CPU + * @brief MCU Clock Frequency (Hertz) + * + * @deprecated + * The \ref F_CPU configuration constant is used for compatibility with the + * \ref group_common_services_delay routines. The common loop-based delay + * routines are designed to use the \ref clk_group modules while anticipating + * support for legacy applications assuming a statically defined clock + * frequency. Applications using a statically configured MCU clock frequency + * can define \ref F_CPU (Hertz), in which case the common delay routines will + * use this value rather than calling sysclk_get_cpu_hz() to get the current + * MCU clock frequency. + */ +#ifndef F_CPU +# define F_CPU sysclk_get_cpu_hz() +#endif + +/** + * @def delay_init + * + * @brief Initialize the delay driver. + * @param fcpu_hz CPU frequency in Hz + * + * @deprecated + * This function is provided for compatibility with ASF applications that + * may not have been updated to configure the system clock via the common + * clock service; e.g. sysclk_init() and a configuration header file are + * used to configure clocks. + * + * The functions in this module call \ref sysclk_get_cpu_hz() function to + * obtain the system clock frequency. + */ +#define delay_init(fcpu_hz) + +/** + * @def delay_s + * @brief Delay in seconds. + * @param delay Delay in seconds + */ +#define delay_s(delay) cpu_delay_ms(1000 * delay, F_CPU) + +/** + * @def delay_ms + * @brief Delay in milliseconds. + * @param delay Delay in milliseconds + */ +#define delay_ms(delay) cpu_delay_ms(delay, F_CPU) + +/** + * @def delay_us + * @brief Delay in microseconds. + * @param delay Delay in microseconds + */ +#define delay_us(delay) cpu_delay_us(delay, F_CPU) + + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* _DELAY_H_ */ diff --git a/DSTAT-temp/src/asf/common/services/delay/xmega/cycle_counter.h b/DSTAT-temp/src/asf/common/services/delay/xmega/cycle_counter.h new file mode 100644 index 0000000..ed48499 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/delay/xmega/cycle_counter.h @@ -0,0 +1,113 @@ +/** + * \file + * + * \brief AVR functions for busy-wait delay loops + * + * Copyright (c) 2011 - 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef _CYCLE_COUNTER_H_ +#define _CYCLE_COUNTER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include + +/** + * @name Convenience functions for busy-wait delay loops + * + * @def delay_cycles + * @brief Delay program execution for a specified number of CPU cycles. + * @param n number of CPU cycles to wait + * + * @def cpu_delay_ms + * @brief Delay program execution for a specified number of milliseconds. + * @param delay number of milliseconds to wait + * @param f_cpu CPU frequency in Hertz + * + * @def cpu_delay_us + * @brief Delay program execution for a specified number of microseconds. + * @param delay number of microseconds to wait + * @param f_cpu CPU frequency in Hertz + * + * @def cpu_ms_2_cy + * @brief Convert milli-seconds into CPU cycles. + * @param ms number of milliseconds + * @param f_cpu CPU frequency in Hertz + * @return the converted number of CPU cycles + * + * @def cpu_us_2_cy + * @brief Convert micro-seconds into CPU cycles. + * @param ms number of microseconds + * @param f_cpu CPU frequency in Hertz + * @return the converted number of CPU cycles + * + * @{ + */ +__always_optimize +static inline void __portable_avr_delay_cycles(unsigned long n) +{ + do { barrier(); } while (--n); +} + +#if !defined(__DELAY_CYCLE_INTRINSICS__) +# define delay_cycles __portable_avr_delay_cycles +# define cpu_ms_2_cy(ms, f_cpu) (((uint64_t)(ms) * (f_cpu) + 999) / 6e3) +# define cpu_us_2_cy(us, f_cpu) (((uint64_t)(us) * (f_cpu) + 999999ul) / 6e6) +#else +# if defined(__GNUC__) +# define delay_cycles __builtin_avr_delay_cycles +# elif defined(__ICCAVR__) +# define delay_cycles __delay_cycles +# endif +# define cpu_ms_2_cy(ms, f_cpu) (((uint64_t)(ms) * (f_cpu) + 999) / 1e3) +# define cpu_us_2_cy(us, f_cpu) (((uint64_t)(us) * (f_cpu) + 999999ul) / 1e6) +#endif + +#define cpu_delay_ms(delay, f_cpu) delay_cycles((uint64_t)cpu_ms_2_cy(delay, f_cpu)) +#define cpu_delay_us(delay, f_cpu) delay_cycles((uint64_t)cpu_us_2_cy(delay, f_cpu)) +//! @} + + +#ifdef __cplusplus +} +#endif + +#endif /* _CYCLE_COUNTER_H_ */ diff --git a/DSTAT-temp/src/asf/common/services/ioport/ioport.h b/DSTAT-temp/src/asf/common/services/ioport/ioport.h new file mode 100644 index 0000000..a27fb7b --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/ioport/ioport.h @@ -0,0 +1,515 @@ +/** + * \file + * + * \brief Common IOPORT service main header file for AVR, UC3 and ARM + * architectures. + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef IOPORT_H +#define IOPORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * \defgroup ioport_group Common IOPORT API + * + * See \ref ioport_quickstart. + * + * This is common IOPORT service for GPIO pin configuration and control in a + * standardized manner across the XMEGA, UC3 and ARM devices. + * + * Port pin control code is optimized for each platform, and should produce + * both compact and fast execution times when used with constant values. + * + * \section dependencies Dependencies + * This driver depends on the following modules: + * - \ref sysclk_group for clock speed and functions. + * @{ + */ + +/** + * \def IOPORT_CREATE_PIN(port, pin) + * \brief Create IOPORT pin number + * + * Create a IOPORT pin number for use with the IOPORT functions. + * + * \param port IOPORT port (e.g. PORTA, PA or PIOA depending on chosen + * architecture) + * \param pin IOPORT zero-based index of the I/O pin + */ + +/** \brief IOPORT pin directions */ +enum ioport_direction { + IOPORT_DIR_INPUT, /*!< IOPORT input direction */ + IOPORT_DIR_OUTPUT, /*!< IOPORT output direction */ +}; + +/** \brief IOPORT levels */ +enum ioport_value { + IOPORT_PIN_LEVEL_LOW, /*!< IOPORT pin value low */ + IOPORT_PIN_LEVEL_HIGH, /*!< IOPORT pin value high */ +}; + +/** \brief IOPORT edge sense modes */ +enum ioport_sense { + IOPORT_SENSE_BOTHEDGES, /*!< IOPORT sense both rising and falling edges */ + IOPORT_SENSE_RISING, /*!< IOPORT sense rising edges */ + IOPORT_SENSE_FALLING, /*!< IOPORT sense falling edges */ +}; + +#if XMEGA +# include "xmega/ioport.h" +# if defined(IOPORT_XMEGA_COMPAT) +# include "xmega/ioport_compat.h" +# endif +#elif UC3 +# include "uc3/ioport.h" +#elif SAM +# if SAM4L +# include "sam/ioport_gpio.h" +# else +# include "sam/ioport_pio.h" +# endif +#endif + +/** + * \brief Initializes the IOPORT service, ready for use. + * + * This function must be called before using any other functions in the IOPORT + * service. + */ +static inline void ioport_init(void) +{ + arch_ioport_init(); +} + +/** + * \brief Enable an IOPORT pin, based on a pin created with \ref + * IOPORT_CREATE_PIN(). + * + * \param pin IOPORT pin to enable + */ +static inline void ioport_enable_pin(ioport_pin_t pin) +{ + arch_ioport_enable_pin(pin); +} + +/** + * \brief Enable multiple pins in a single IOPORT port. + * + * \param port IOPORT port to enable + * \param mask Mask of pins within the port to enable + */ +static inline void ioport_enable_port(ioport_port_t port, + ioport_port_mask_t mask) +{ + arch_ioport_enable_port(port, mask); +} + +/** + * \brief Disable IOPORT pin, based on a pin created with \ref + * IOPORT_CREATE_PIN(). + * + * \param pin IOPORT pin to disable + */ +static inline void ioport_disable_pin(ioport_pin_t pin) +{ + arch_ioport_disable_pin(pin); +} + +/** + * \brief Disable multiple pins in a single IOPORT port. + * + * \param port IOPORT port to disable + * \param mask Pin mask of pins to disable + */ +static inline void ioport_disable_port(ioport_port_t port, + ioport_port_mask_t mask) +{ + arch_ioport_disable_port(port, mask); +} + +/** + * \brief Set multiple pin modes in a single IOPORT port, such as pull-up, + * pull-down, etc. configuration. + * + * \param port IOPORT port to configure + * \param mask Pin mask of pins to configure + * \param mode Mode masks to configure for the specified pins (\ref + * ioport_modes) + */ +static inline void ioport_set_port_mode(ioport_port_t port, + ioport_port_mask_t mask, ioport_mode_t mode) +{ + arch_ioport_set_port_mode(port, mask, mode); +} + +/** + * \brief Set pin mode for one single IOPORT pin. + * + * \param pin IOPORT pin to configure + * \param mode Mode masks to configure for the specified pin (\ref ioport_modes) + */ +static inline void ioport_set_pin_mode(ioport_pin_t pin, ioport_mode_t mode) +{ + arch_ioport_set_pin_mode(pin, mode); +} + +/** + * \brief Reset multiple pin modes in a specified IOPORT port to defaults. + * + * \param port IOPORT port to configure + * \param mask Mask of pins whose mode configuration is to be reset + */ +static inline void ioport_reset_port_mode(ioport_port_t port, + ioport_port_mask_t mask) +{ + arch_ioport_set_port_mode(port, mask, 0); +} + +/** + * \brief Reset pin mode configuration for a single IOPORT pin + * + * \param pin IOPORT pin to configure + */ +static inline void ioport_reset_pin_mode(ioport_pin_t pin) +{ + arch_ioport_set_pin_mode(pin, 0); +} + +/** + * \brief Set I/O direction for a group of pins in a single IOPORT. + * + * \param port IOPORT port to configure + * \param mask Pin mask of pins to configure + * \param dir Direction to set for the specified pins (\ref ioport_direction) + */ +static inline void ioport_set_port_dir(ioport_port_t port, + ioport_port_mask_t mask, enum ioport_direction dir) +{ + arch_ioport_set_port_dir(port, mask, dir); +} + +/** + * \brief Set direction for a single IOPORT pin. + * + * \param pin IOPORT pin to configure + * \param dir Direction to set for the specified pin (\ref ioport_direction) + */ +static inline void ioport_set_pin_dir(ioport_pin_t pin, + enum ioport_direction dir) +{ + arch_ioport_set_pin_dir(pin, dir); +} + +/** + * \brief Set an IOPORT pin to a specified logical value. + * + * \param pin IOPORT pin to configure + * \param level Logical value of the pin + */ +static inline void ioport_set_pin_level(ioport_pin_t pin, bool level) +{ + arch_ioport_set_pin_level(pin, level); +} + +/** + * \brief Set a group of IOPORT pins in a single port to a specified logical + * value. + * + * \param port IOPORT port to write to + * \param mask Pin mask of pins to modify + * \param level Level of the pins to be modified + */ +static inline void ioport_set_port_level(ioport_port_t port, + ioport_port_mask_t mask, ioport_port_mask_t level) +{ + arch_ioport_set_port_level(port, mask, level); +} + +/** + * \brief Get current value of an IOPORT pin, which has been configured as an + * input. + * + * \param pin IOPORT pin to read + * \return Current logical value of the specified pin + */ +static inline bool ioport_get_pin_level(ioport_pin_t pin) +{ + return arch_ioport_get_pin_level(pin); +} + +/** + * \brief Get current value of several IOPORT pins in a single port, which have + * been configured as an inputs. + * + * \param port IOPORT port to read + * \param mask Pin mask of pins to read + * \return Logical levels of the specified pins from the read port, returned as + * a mask. + */ +static inline ioport_port_mask_t ioport_get_port_level(ioport_pin_t port, + ioport_port_mask_t mask) +{ + return arch_ioport_get_port_level(port, mask); +} + +/** + * \brief Toggle the value of an IOPORT pin, which has previously configured as + * an output. + * + * \param pin IOPORT pin to toggle + */ +static inline void ioport_toggle_pin_level(ioport_pin_t pin) +{ + arch_ioport_toggle_pin_level(pin); +} + +/** + * \brief Toggle the values of several IOPORT pins located in a single port. + * + * \param port IOPORT port to modify + * \param mask Pin mask of pins to toggle + */ +static inline void ioport_toggle_port_level(ioport_port_t port, + ioport_port_mask_t mask) +{ + arch_ioport_toggle_port_level(port, mask); +} + +/** + * \brief Set the pin sense mode of a single IOPORT pin. + * + * \param pin IOPORT pin to configure + * \param pin_sense Edge to sense for the pin (\ref ioport_sense) + */ +static inline void ioport_set_pin_sense_mode(ioport_pin_t pin, + enum ioport_sense pin_sense) +{ + arch_ioport_set_pin_sense_mode(pin, pin_sense); +} + +/** + * \brief Set the pin sense mode of a multiple IOPORT pins on a single port. + * + * \param port IOPORT port to configure + * \param mask Bitmask if pins whose edge sense is to be configured + * \param pin_sense Edge to sense for the pins (\ref ioport_sense) + */ +static inline void ioport_set_port_sense_mode(ioport_port_t port, + ioport_port_mask_t mask, + enum ioport_sense pin_sense) +{ + arch_ioport_set_port_sense_mode(port, mask, pin_sense); +} + +/** + * \brief Convert a pin ID into a its port ID. + * + * \param pin IOPORT pin ID to convert + * \retval Port ID for the given pin ID + */ +static inline ioport_port_t ioport_pin_to_port_id(ioport_pin_t pin) +{ + return arch_ioport_pin_to_port_id(pin); +} + +/** + * \brief Convert a pin ID into a bitmask mask for the given pin on its port. + * + * \param pin IOPORT pin ID to convert + * \retval Bitmask with a bit set that corresponds to the given pin ID in its port + */ +static inline ioport_port_mask_t ioport_pin_to_mask(ioport_pin_t pin) +{ + return arch_ioport_pin_to_mask(pin); +} + +/** @} */ + +/** + * \page ioport_quickstart Quick start guide for the common IOPORT service + * + * This is the quick start guide for the \ref ioport_group, with + * step-by-step instructions on how to configure and use the service in a + * selection of use cases. + * + * The use cases contain several code fragments. The code fragments in the + * steps for setup can be copied into a custom initialization function, while + * the steps for usage can be copied into, e.g., the main application function. + * + * \section ioport_quickstart_basic Basic use case + * In this use case we will configure one IO pin for button input and one for + * LED control. Then it will read the button state and output it on the LED. + * + * \section ioport_quickstart_basic_setup Setup steps + * + * \subsection ioport_quickstart_basic_setup_code Example code + * \code + * #define MY_LED IOPORT_CREATE_PIN(PORTA, 5) + * #define MY_BUTTON IOPORT_CREATE_PIN(PORTA, 6) + * + * ioport_init(); + * + * ioport_set_pin_dir(MY_LED, IOPORT_DIR_OUTPUT); + * ioport_set_pin_dir(MY_BUTTON, IOPORT_DIR_INPUT); + * ioport_set_pin_mode(MY_BUTTON, IOPORT_MODE_PULLUP); + * \endcode + * + * \subsection ioport_quickstart_basic_setup_flow Workflow + * -# It's useful to give the GPIOs symbolic names and this can be done with + * the \ref IOPORT_CREATE_PIN macro. We define one for a LED and one for a + * button. + * - \code + * #define MY_LED IOPORT_CREATE_PIN(PORTA, 5) + * #define MY_BUTTON IOPORT_CREATE_PIN(PORTA, 6) + * \endcode + * - \note The usefulness of the \ref IOPORT_CREATE_PIN macro and port names + * differ between architectures: + * - XMEGA: Use \ref IOPORT_CREATE_PIN macro with port definitions + * PORTA, PORTB ... + * - UC3: Most convenient to pick up the device header file pin definition + * and us it directly. E.g.: AVR32_PIN_PB06 + * - SAM: Most convenient to pick up the device header file pin definition + * and us it directly. E.g.: PIO_PA5_IDX
+ * \ref IOPORT_CREATE_PIN can also be used with port definitions + * PIOA, PIOB ... + * -# Initialize the ioport service. This typically enables the IO module if + * needed. + * - \code ioport_init(); \endcode + * -# Set the LED GPIO as output: + * - \code ioport_set_pin_dir(MY_LED, IOPORT_DIR_OUTPUT); \endcode + * -# Set the button GPIO as input: + * - \code ioport_set_pin_dir(MY_BUTTON, IOPORT_DIR_INPUT); \endcode + * -# Enable pull-up for the button GPIO: + * - \code ioport_set_pin_mode(MY_BUTTON, IOPORT_MODE_PULLUP); \endcode + * + * \section ioport_quickstart_basic_usage Usage steps + * + * \subsection ioport_quickstart_basic_usage_code Example code + * \code + * bool value; + * + * value = ioport_get_pin_level(MY_BUTTON); + * ioport_set_pin_level(MY_LED, value); + * \endcode + * + * \subsection ioport_quickstart_basic_usage_flow Workflow + * -# Define a boolean variable for state storage: + * - \code bool value; \endcode + * -# Read out the button level into variable value: + * - \code value = ioport_get_pin_level(MY_BUTTON); \endcode + * -# Set the LED to read out value from the button: + * - \code ioport_set_pin_level(MY_LED, value); \endcode + * + * \section ioport_quickstart_advanced Advanced use cases + * - \subpage ioport_quickstart_use_case_1 : Port access + */ + +/** + * \page ioport_quickstart_use_case_1 Advanced use case doing port access + * + * In this case we will read out the pins from one whole port and write the + * read value to another port. + * + * \section ioport_quickstart_use_case_1_setup Setup steps + * + * \subsection ioport_quickstart_use_case_1_setup_code Example code + * \code + * #define IN_PORT IOPORT_PORTA + * #define OUT_PORT IOPORT_PORTB + * #define MASK 0x00000060 + * + * ioport_init(); + * + * ioport_set_port_dir(IN_PORT, MASK, IOPORT_DIR_INPUT); + * ioport_set_port_dir(OUT_PORT, MASK, IOPORT_DIR_OUTPUT); + * \endcode + * + * \subsection ioport_quickstart_basic_setup_flow Workflow + * -# It's useful to give the ports symbolic names: + * - \code + * #define IN_PORT IOPORT_PORTA + * #define OUT_PORT IOPORT_PORTB + * \endcode + * - \note The port names differ between architectures: + * - XMEGA: There are predefined names for ports: IOPORT_PORTA, + * IOPORT_PORTB ... + * - UC3: Use the index value of the different IO blocks: 0, 1 ... + * - SAM: There are predefined names for ports: IOPORT_PIOA, IOPORT_PIOB + * ... + * -# Also useful to define a mask for the bits to work with: + * - \code #define MASK 0x00000060 \endcode + * -# Initialize the ioport service. This typically enables the IO module if + * needed. + * - \code ioport_init(); \endcode + * -# Set one of the ports as input: + * - \code ioport_set_pin_dir(IN_PORT, MASK, IOPORT_DIR_INPUT); \endcode + * -# Set the other port as output: + * - \code ioport_set_pin_dir(OUT_PORT, MASK, IOPORT_DIR_OUTPUT); \endcode + * + * \section ioport_quickstart_basic_usage Usage steps + * + * \subsection ioport_quickstart_basic_usage_code Example code + * \code + * ioport_port_mask_t value; + * + * value = ioport_get_port_level(IN_PORT, MASK); + * ioport_set_port_level(OUT_PORT, MASK, value); + * \endcode + * + * \subsection ioport_quickstart_basic_usage_flow Workflow + * -# Define a variable for port date storage: + * - \code ioport_port_mask_t value; \endcode + * -# Read out from one port: + * - \code value = ioport_get_port_level(IN_PORT, MASK); \endcode + * -# Put the read data out on the other port: + * - \code ioport_set_port_level(OUT_PORT, MASK, value); \endcode + */ + +#ifdef __cplusplus +} +#endif + +#endif /* IOPORT_H */ diff --git a/DSTAT-temp/src/asf/common/services/ioport/xmega/ioport.h b/DSTAT-temp/src/asf/common/services/ioport/xmega/ioport.h new file mode 100644 index 0000000..5b2f21f --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/ioport/xmega/ioport.h @@ -0,0 +1,337 @@ +/** + * \file + * + * \brief XMEGA architecture specific IOPORT service implementation header file. + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef IOPORT_XMEGA_H +#define IOPORT_XMEGA_H + +#define IOPORT_CREATE_PIN(port, pin) ((IOPORT_ ## port) * 8 + (pin)) +#define IOPORT_BASE_ADDRESS 0x600 +#define IOPORT_PORT_OFFSET 0x20 + +/** \name IOPORT port numbers */ +/** @{ */ +#if !XMEGA_B3 +# define IOPORT_PORTA 0 +#endif + +#define IOPORT_PORTB 1 +#define IOPORT_PORTC 2 +#define IOPORT_PORTD 3 + +#if !XMEGA_B3 +# define IOPORT_PORTE 4 +#endif + +#if XMEGA_A1 || XMEGA_A1U || XMEGA_A3 || XMEGA_A3U || XMEGA_A3B || XMEGA_A3BU ||\ + XMEGA_C3 || XMEGA_D3 +# define IOPORT_PORTF 5 +#endif + +#if XMEGA_B1 || XMEGA_B3 +# define IOPORT_PORTG 6 +#endif + +#if XMEGA_A1 || XMEGA_A1U +# define IOPORT_PORTH 7 +# define IOPORT_PORTJ 8 +# define IOPORT_PORTK 9 +#endif + +#if XMEGA_B1 || XMEGA_B3 +# define IOPORT_PORTM 11 +#endif + +#if XMEGA_A1 || XMEGA_A1U +# define IOPORT_PORTQ 14 +#endif + +#define IOPORT_PORTR 15 +/** @} */ + +/** + * \weakgroup ioport_group + * \section ioport_modes IOPORT Modes + * + * For details on these please see the XMEGA Manual. + * + * @{ + */ + +/** \name IOPORT Mode bit definitions */ +/** @{ */ +#define IOPORT_MODE_TOTEM (0x00 << 3) /*!< Totem-pole */ +#define IOPORT_MODE_BUSKEEPER (0x01 << 3) /*!< Buskeeper */ +#define IOPORT_MODE_PULLDOWN (0x02 << 3) /*!< Pull-down */ +#define IOPORT_MODE_PULLUP (0x03 << 3) /*!< Pull-up */ +#define IOPORT_MODE_WIREDOR (0x04 << 3) /*!< Wired OR */ +#define IOPORT_MODE_WIREDAND (0x05 << 3) /*!< Wired AND */ +#define IOPORT_MODE_WIREDORPULL (0x06 << 3) /*!< Wired OR with pull-down */ +#define IOPORT_MODE_WIREDANDPULL (0x07 << 3) /*!< Wired AND with pull-up */ +#define IOPORT_MODE_INVERT_PIN (0x01 << 6) /*!< Invert output and input */ +#define IOPORT_MODE_SLEW_RATE_LIMIT (0x01 << 7) /*!< Slew rate limiting */ +/** @} */ + +/** @} */ + +typedef uint8_t ioport_mode_t; +typedef uint8_t ioport_pin_t; +typedef uint8_t ioport_port_t; +typedef uint8_t ioport_port_mask_t; + +__always_inline static ioport_port_t arch_ioport_pin_to_port_id(ioport_pin_t pin) +{ + return pin >> 3; +} + +__always_inline static PORT_t *arch_ioport_port_to_base(ioport_port_t port) +{ + return (PORT_t *)((uintptr_t)IOPORT_BASE_ADDRESS + + (port * IOPORT_PORT_OFFSET)); +} + +__always_inline static PORT_t *arch_ioport_pin_to_base(ioport_pin_t pin) +{ + return arch_ioport_port_to_base(arch_ioport_pin_to_port_id(pin)); +} + +__always_inline static ioport_port_mask_t arch_ioport_pin_to_mask(ioport_pin_t pin) +{ + return 1U << (pin & 0x07); +} + +__always_inline static ioport_port_mask_t arch_ioport_pin_to_index(ioport_pin_t pin) +{ + return (pin & 0x07); +} + +__always_inline static void arch_ioport_init(void) +{ + +} + +__always_inline static void arch_ioport_enable_port(ioport_port_t port, + ioport_port_mask_t mask) +{ + PORT_t *base = arch_ioport_port_to_base(port); + volatile uint8_t *pin_ctrl = &base->PIN0CTRL; + + uint8_t flags = cpu_irq_save(); + + for (uint8_t i = 0; i < 8; i++) { + if (mask & arch_ioport_pin_to_mask(i)) { + pin_ctrl[i] &= ~PORT_ISC_gm; + } + } + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_enable_pin(ioport_pin_t pin) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + volatile uint8_t *pin_ctrl = + (&base->PIN0CTRL + arch_ioport_pin_to_index(pin)); + + uint8_t flags = cpu_irq_save(); + + *pin_ctrl &= ~PORT_ISC_gm; + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_disable_port(ioport_port_t port, + ioport_port_mask_t mask) +{ + PORT_t *base = arch_ioport_port_to_base(port); + volatile uint8_t *pin_ctrl = &base->PIN0CTRL; + + uint8_t flags = cpu_irq_save(); + + for (uint8_t i = 0; i < 8; i++) { + if (mask & arch_ioport_pin_to_mask(i)) { + pin_ctrl[i] |= PORT_ISC_INPUT_DISABLE_gc; + } + } + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_disable_pin(ioport_pin_t pin) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + volatile uint8_t *pin_ctrl = + (&base->PIN0CTRL + arch_ioport_pin_to_index(pin)); + + uint8_t flags = cpu_irq_save(); + + *pin_ctrl |= PORT_ISC_INPUT_DISABLE_gc; + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_set_port_mode(ioport_port_t port, + ioport_port_mask_t mask, ioport_mode_t mode) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + PORTCFG.MPCMASK = mask; + base->PIN0CTRL = mode; +} + +__always_inline static void arch_ioport_set_pin_mode(ioport_pin_t pin, + ioport_mode_t mode) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + PORTCFG.MPCMASK = arch_ioport_pin_to_mask(pin); + base->PIN0CTRL = mode; +} + +__always_inline static void arch_ioport_set_port_dir(ioport_port_t port, + ioport_port_mask_t mask, enum ioport_direction dir) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + if (dir == IOPORT_DIR_OUTPUT) { + base->DIRSET = mask; + } else if (dir == IOPORT_DIR_INPUT) { + base->DIRCLR = mask; + } +} + +__always_inline static void arch_ioport_set_pin_dir(ioport_pin_t pin, + enum ioport_direction dir) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + if (dir == IOPORT_DIR_OUTPUT) { + base->DIRSET = arch_ioport_pin_to_mask(pin); + } else if (dir == IOPORT_DIR_INPUT) { + base->DIRCLR = arch_ioport_pin_to_mask(pin); + } +} + +__always_inline static void arch_ioport_set_pin_level(ioport_pin_t pin, + bool level) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + if (level) { + base->OUTSET = arch_ioport_pin_to_mask(pin); + } else { + base->OUTCLR = arch_ioport_pin_to_mask(pin); + } +} + +__always_inline static void arch_ioport_set_port_level(ioport_port_t port, + ioport_port_mask_t mask, ioport_port_mask_t level) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + base->OUTSET = mask & level; + base->OUTCLR = mask & ~level; +} + +__always_inline static bool arch_ioport_get_pin_level(ioport_pin_t pin) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + return base->IN & arch_ioport_pin_to_mask(pin); +} + +__always_inline static ioport_port_mask_t arch_ioport_get_port_level( + ioport_port_t port, ioport_port_mask_t mask) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + return base->IN & mask; +} + +__always_inline static void arch_ioport_toggle_pin_level(ioport_pin_t pin) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + base->OUTTGL = arch_ioport_pin_to_mask(pin); +} + +__always_inline static void arch_ioport_toggle_port_level(ioport_port_t port, + ioport_port_mask_t mask) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + base->OUTTGL = mask; +} + +__always_inline static void arch_ioport_set_pin_sense_mode(ioport_pin_t pin, + enum ioport_sense pin_sense) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + volatile uint8_t *pin_ctrl = + (&base->PIN0CTRL + arch_ioport_pin_to_index(pin)); + + uint8_t flags = cpu_irq_save(); + + *pin_ctrl &= ~PORT_ISC_gm; + *pin_ctrl |= (pin_sense & PORT_ISC_gm); + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_set_port_sense_mode(ioport_port_t port, + ioport_port_mask_t mask, enum ioport_sense pin_sense) +{ + PORT_t *base = arch_ioport_port_to_base(port); + volatile uint8_t *pin_ctrl = &base->PIN0CTRL; + uint8_t new_sense_bits = (pin_sense & PORT_ISC_gm); + + uint8_t flags = cpu_irq_save(); + + for (uint8_t i = 0; i < 8; i++) { + if (mask & arch_ioport_pin_to_mask(i)) { + pin_ctrl[i] = (pin_ctrl[i] & ~PORT_ISC_gm) | new_sense_bits; + } + } + + cpu_irq_restore(flags); +} + +#endif /* IOPORT_XMEGA_H */ diff --git a/DSTAT-temp/src/asf/common/services/ioport/xmega/ioport_compat.c b/DSTAT-temp/src/asf/common/services/ioport/xmega/ioport_compat.c new file mode 100644 index 0000000..af81a81 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/ioport/xmega/ioport_compat.c @@ -0,0 +1,70 @@ +/** + * \file + * + * \brief XMEGA legacy IOPORT software compatibility driver interface. + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include "ioport_compat.h" + +#if defined(IOPORT_XMEGA_COMPAT) +void ioport_configure_port_pin(void *port, pin_mask_t pin_mask, + port_pin_flags_t flags) +{ + uint8_t pin; + + for (pin = 0; pin < 8; pin++) { + if (pin_mask & (1 << pin)) { + *((uint8_t *)port + PORT_PIN0CTRL + pin) = flags >> 8; + } + } + /* Select direction and initial pin state */ + if (flags & IOPORT_DIR_OUTPUT) { + if (flags & IOPORT_INIT_HIGH) { + *((uint8_t *)port + PORT_OUTSET) = pin_mask; + } else { + *((uint8_t *)port + PORT_OUTCLR) = pin_mask; + } + + *((uint8_t *)port + PORT_DIRSET) = pin_mask; + } else { + *((uint8_t *)port + PORT_DIRCLR) = pin_mask; + } +} + +#endif diff --git a/DSTAT-temp/src/asf/common/services/ioport/xmega/ioport_compat.h b/DSTAT-temp/src/asf/common/services/ioport/xmega/ioport_compat.h new file mode 100644 index 0000000..91ed6ec --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/ioport/xmega/ioport_compat.h @@ -0,0 +1,315 @@ +/** + * \file + * + * \brief XMEGA legacy IOPORT software compatibility driver interface header + * file. + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef IOPORT_XMEGA_COMPAT_H_ +#define IOPORT_XMEGA_COMPAT_H_ + +#include "../ioport.h" + +/** + * \brief A pin mask + * + * This type is used to describe the port pin mask on the part. + */ +typedef uint8_t pin_mask_t; + +/** + * \brief A PORT pin + * + * This type is used to describe the PORT pins on the part. + */ +typedef uint8_t port_pin_t; + +/** + * \brief Pin configuration flags + * + * This is a bitmask containing configuration flags for the pins that shall be + * configured. + */ +typedef uint16_t port_pin_flags_t; + +/** + * \brief A port id + * + * This type is used to describe the port id on the part (0 is PORTA). + */ +typedef uint8_t port_id_t; + +/** \name Initial Output State Flags */ +/** @{ */ +#define IOPORT_INIT_LOW (0 << 1) /*!< Initial Output State Low */ +#define IOPORT_INIT_HIGH (1 << 1) /*!< Initial Output State High */ +/** @} */ + +/** \name Input/Sense Configuration Flags */ +/** @{ */ +#define IOPORT_BOTHEDGES (0 << 8) /*!< Sense Both Edges */ +#define IOPORT_RISING (1 << 8) /*!< Sense Rising Edge */ +#define IOPORT_FALLING (2 << 8) /*!< Sense Falling Edge */ +#define IOPORT_LEVEL (3 << 8) /*!< Sense Low Level */ +#define IOPORT_INPUT_DISABLE (7 << 8) /*!< Input Buffer Disabled */ +/** @} */ + +/** \name Output and Pull Configuration Flags */ +/** @{ */ +#define IOPORT_TOTEM (0 << 11) /*!< Normal push/pull output */ +#define IOPORT_BUSKEEPER (1 << 11) /*!< Bus Keeper */ +#define IOPORT_PULL_DOWN (2 << 11) /*!< Pull-Down (when input) */ +#define IOPORT_PULL_UP (3 << 11) /*!< Pull-Up (when input) */ +#define IOPORT_WIRED_OR (4 << 11) /*!< Wired OR */ +#define IOPORT_WIRED_AND (5 << 11) /*!< Wired AND */ +#define IOPORT_WIRED_OR_PULL_DOWN (6 << 11) /*!< Wired OR and Pull-Down */ +#define IOPORT_WIRED_AND_PULL_UP (7 << 11) /*!< Wired AND and Pull-Up */ +/** @} */ + +/** \name Inverted I/O Configuration Flags */ +/** @{ */ +#define IOPORT_INV_ENABLED (1 << 14) /*!< I/O is Inverted */ +#define IOPORT_INV_DISABLE (0 << 14) /*!< I/O is Not Inverted */ +/** @} */ + +/** \name Slew Rate Limit Configuration Flags */ +/** @{ */ +#define IOPORT_SRL_ENABLED (1 << 15) /*!< Slew Rate Limit Enabled */ +#define IOPORT_SRL_DISABLED (0 << 15) /*!< Slew Rate Limit Disabled */ +/** @} */ + +/** + * \internal + * \name PORT fields structure offset + * + * These macros are used to compute the field offset number with the PORT_t + * structure. + */ +/** @{ */ +#define PORT_DIR 0x00 /*!< Data Direction */ +#define PORT_DIRSET 0x01 /*!< Data Direction Set */ +#define PORT_DIRCLR 0x02 /*!< Data Direction Clear */ +#define PORT_DIRTGL 0x03 /*!< Data Direction Toggle */ +#define PORT_OUT 0x04 /*!< Data Output Value */ +#define PORT_OUTSET 0x05 /*!< Data Output Value Set */ +#define PORT_OUTCLR 0x06 /*!< Data Output Value Clear */ +#define PORT_OUTTGL 0x07 /*!< Data Output Value Toggle */ +#define PORT_IN 0x08 /*!< Data Input Value */ +#define PORT_INTCTRL 0x09 /*!< Interrupt Control */ +#define PORT_INT0MASK 0x0A /*!< Interrupt 0 Mask */ +#define PORT_INT1MASK 0x0B /*!< Interrupt 1 Mask */ +#define PORT_INTFLAGS 0x0C /*!< Interrupt Flags */ +#define PORT_PIN0CTRL 0x10 /*!< Pin 0 Configuration */ +#define PORT_PIN1CTRL 0x11 /*!< Pin 1 Configuration */ +#define PORT_PIN2CTRL 0x12 /*!< Pin 2 Configuration */ +#define PORT_PIN3CTRL 0x13 /*!< Pin 3 Configuration */ +#define PORT_PIN4CTRL 0x14 /*!< Pin 4 Configuration */ +#define PORT_PIN5CTRL 0x15 /*!< Pin 5 Configuration */ +#define PORT_PIN6CTRL 0x16 /*!< Pin 6 Configuration */ +#define PORT_PIN7CTRL 0x17 /*!< Pin 7 Configuration */ +/** @} */ + +static inline PORT_t *ioport_pin_to_port(port_pin_t pin) +{ + return arch_ioport_pin_to_base(pin); +} + +static inline PORT_t *ioport_id_pin_to_port(port_id_t port) +{ + return arch_ioport_port_to_base(port); +} + +/** + * \brief Configure the IO PORT pin function for a set of pins on a port + * + * \param port Pointer to the port + * \param pin_mask Mask containing the pins that should be configured + * \param flags Bitmask of flags specifying additional configuration + * parameters. + */ +void ioport_configure_port_pin(void *port, pin_mask_t pin_mask, + port_pin_flags_t flags); + +/** + * \brief Select the port function for a single pin + * + * \param pin The pin to configure + * \param flags Bitmask of flags specifying additional configuration + * parameters. + */ +static inline void ioport_configure_pin(port_pin_t pin, port_pin_flags_t flags) +{ + ioport_configure_port_pin(arch_ioport_pin_to_base(pin), + arch_ioport_pin_to_mask(pin), flags); +} + +/** + * \brief Configure a group of I/O pins on a specified port number + * + * \param port The port number + * \param pin_mask The pin mask to configure + * \param flags Bitmask of flags specifying additional configuration + * parameters. + */ +static inline void ioport_configure_group(port_id_t port, pin_mask_t pin_mask, + port_pin_flags_t flags) +{ + ioport_configure_port_pin(arch_ioport_port_to_base(port), pin_mask, flags); +} + +/** + * \brief Drive a PORT pin to a given state + * + * This function will only have an effect if \a pin is configured as + * an output. + * + * \param pin A number identifying the pin to act on. + * \param value The desired state of the pin. \a true means drive the + * pin high (towards Vdd), while \a false means drive the pin low + * (towards Vss). + */ +static inline void ioport_set_value(port_pin_t pin, bool value) +{ + arch_ioport_set_pin_level(pin, value); +} + +/** + * \brief Drive a PORT pin to a low level + * + * This function will only have an effect if \a pin is configured as + * an output. + * + * \param pin A number identifying the pin to act on. + */ +static inline void ioport_set_pin_low(port_pin_t pin) +{ + arch_ioport_set_pin_level(pin, false); +} + +/** + * \brief Drive a PORT pin to a high level + * + * This function will only have an effect if \a pin is configured as + * an output. + * + * \param pin A number identifying the pin to act on. + */ +static inline void ioport_set_pin_high(port_pin_t pin) +{ + arch_ioport_set_pin_level(pin, true); +} + +/** + * \brief Read the current state of a PORT pin + * + * \param pin A number identifying the pin to read. + * \retval true The pin is currently high (close to Vdd) + * \retval false The pin is currently low (close to Vss) + */ +static inline bool ioport_get_value(port_pin_t pin) +{ + return arch_ioport_get_pin_level(pin); +} + +/** + * \brief Read the current state of a PORT pin and test high level + * + * \param pin A number identifying the pin to read. + * \retval true The pin is currently high (close to Vdd) + * \retval false The pin is currently low (close to Vss) + */ +static inline bool ioport_pin_is_high(port_pin_t pin) +{ + return (arch_ioport_get_pin_level(pin) == true); +} + +/** + * \brief Read the current state of a PORT pin and test high level + * + * \param pin A number identifying the pin to read. + * \retval true The pin is currently high (close to Vdd) + * \retval false The pin is currently low (close to Vss) + */ +static inline bool ioport_pin_is_low(port_pin_t pin) +{ + return (arch_ioport_get_pin_level(pin) == false); +} + +/** + * \brief Toggle the current state of a PORT pin + * + * \param pin A number identifying the pin to act on. + */ +static inline void ioport_toggle_pin(port_pin_t pin) +{ + arch_ioport_toggle_pin_level(pin); +} + +/*! \brief Drives a group of I/O pin of a port to high level. + * + * \param port_id The port number. + * \param port_mask The mask. + */ +static inline void ioport_set_group_high(port_id_t port_id, + pin_mask_t port_mask) +{ + arch_ioport_set_port_level(port_id, port_mask, port_mask); +} + +/*! \brief Drives a group of I/O pin of a port to low level. + * + * \param port_id The port number. + * \param port_mask The mask. + */ +static inline void ioport_set_group_low(port_id_t port_id, pin_mask_t port_mask) +{ + arch_ioport_set_port_level(port_id, port_mask, 0); +} + +/*! \brief Toggles a group of I/O pin of a port. + * + * \param port_id The port number. + * \param port_mask The mask. + */ +static inline void ioport_tgl_group(port_id_t port_id, pin_mask_t port_mask) +{ + arch_ioport_toggle_port_level(port_id, port_mask); +} + +#endif /* IOPORT_COMPAT_H_ */ diff --git a/DSTAT-temp/src/asf/common/services/sleepmgr/sleepmgr.h b/DSTAT-temp/src/asf/common/services/sleepmgr/sleepmgr.h new file mode 100644 index 0000000..92a29c7 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/sleepmgr/sleepmgr.h @@ -0,0 +1,241 @@ +/** + * \file + * + * \brief Sleep manager + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef SLEEPMGR_H +#define SLEEPMGR_H + +#include +#include +#include + +#if (SAM3S || SAM3U || SAM3N || SAM3XA || SAM4S) +# include "sam/sleepmgr.h" +#elif XMEGA +# include "xmega/sleepmgr.h" +#elif (defined(__GNUC__) && defined(__AVR32__)) || (defined(__ICCAVR32__) || defined(__AAVR32__)) +# include "uc3/sleepmgr.h" +#elif SAM4L +# include "sam4l/sleepmgr.h" +#else +# error Unsupported device. +#endif + +/** + * \defgroup sleepmgr_group Sleep manager + * + * The sleep manager is a service for ensuring that the device is not put to + * sleep in deeper sleep modes than the system (e.g., peripheral drivers, + * services or the application) allows at any given time. + * + * It is based on the use of lock counting for the individual sleep modes, and + * will put the device to sleep in the shallowest sleep mode that has a non-zero + * lock count. The drivers/services/application can change these counts by use + * of \ref sleepmgr_lock_mode and \ref sleepmgr_unlock_mode. + * Refer to \ref sleepmgr_mode for a list of the sleep modes available for + * locking, and the device datasheet for information on their effect. + * + * The application must supply the file \ref conf_sleepmgr.h. + * + * For the sleep manager to be enabled, the symbol \ref CONFIG_SLEEPMGR_ENABLE + * must be defined, e.g., in \ref conf_sleepmgr.h. If this symbol is not + * defined, the functions are replaced with dummy functions and no RAM is used. + * + * @{ + */ + +/** + * \def CONFIG_SLEEPMGR_ENABLE + * \brief Configuration symbol for enabling the sleep manager + * + * If this symbol is not defined, the functions of this service are replaced + * with dummy functions. This is useful for reducing code size and execution + * time if the sleep manager is not needed in the application. + * + * This symbol may be defined in \ref conf_sleepmgr.h. + */ +#if defined(__DOXYGEN__) && !defined(CONFIG_SLEEPMGR_ENABLE) +# define CONFIG_SLEEPMGR_ENABLE +#endif + +/** + * \enum sleepmgr_mode + * \brief Sleep mode locks + * + * Identifiers for the different sleep mode locks. + */ + +/** + * \brief Initialize the lock counts + * + * Sets all lock counts to 0, except the very last one, which is set to 1. This + * is done to simplify the algorithm for finding the deepest allowable sleep + * mode in \ref sleepmgr_enter_sleep. + */ +static inline void sleepmgr_init(void) +{ +#ifdef CONFIG_SLEEPMGR_ENABLE + uint8_t i; + + for (i = 0; i < SLEEPMGR_NR_OF_MODES - 1; i++) { + sleepmgr_locks[i] = 0; + } + sleepmgr_locks[SLEEPMGR_NR_OF_MODES - 1] = 1; +#endif /* CONFIG_SLEEPMGR_ENABLE */ +} + +/** + * \brief Increase lock count for a sleep mode + * + * Increases the lock count for \a mode to ensure that the sleep manager does + * not put the device to sleep in the deeper sleep modes. + * + * \param mode Sleep mode to lock. + */ +static inline void sleepmgr_lock_mode(enum sleepmgr_mode mode) +{ +#ifdef CONFIG_SLEEPMGR_ENABLE + irqflags_t flags; + + Assert(sleepmgr_locks[mode] < 0xff); + + // Enter a critical section + flags = cpu_irq_save(); + + ++sleepmgr_locks[mode]; + + // Leave the critical section + cpu_irq_restore(flags); +#endif /* CONFIG_SLEEPMGR_ENABLE */ +} + +/** + * \brief Decrease lock count for a sleep mode + * + * Decreases the lock count for \a mode. If the lock count reaches 0, the sleep + * manager can put the device to sleep in the deeper sleep modes. + * + * \param mode Sleep mode to unlock. + */ +static inline void sleepmgr_unlock_mode(enum sleepmgr_mode mode) +{ +#ifdef CONFIG_SLEEPMGR_ENABLE + irqflags_t flags; + + Assert(sleepmgr_locks[mode]); + + // Enter a critical section + flags = cpu_irq_save(); + + --sleepmgr_locks[mode]; + + // Leave the critical section + cpu_irq_restore(flags); +#endif /* CONFIG_SLEEPMGR_ENABLE */ +} + + /** + * \brief Retrieves the deepest allowable sleep mode + * + * Searches through the sleep mode lock counts, starting at the shallowest sleep + * mode, until the first non-zero lock count is found. The deepest allowable + * sleep mode is then returned. + */ +static inline enum sleepmgr_mode sleepmgr_get_sleep_mode(void) +{ + enum sleepmgr_mode sleep_mode = SLEEPMGR_ACTIVE; + +#ifdef CONFIG_SLEEPMGR_ENABLE + uint8_t *lock_ptr = sleepmgr_locks; + + // Find first non-zero lock count, starting with the shallowest modes. + while (!(*lock_ptr)) { + lock_ptr++; + sleep_mode++; + } + + // Catch the case where one too many sleepmgr_unlock_mode() call has been + // performed on the deepest sleep mode. + Assert((uintptr_t)(lock_ptr - sleepmgr_locks) < SLEEPMGR_NR_OF_MODES); + +#endif /* CONFIG_SLEEPMGR_ENABLE */ + + return sleep_mode; +} + +/** + * \fn sleepmgr_enter_sleep + * \brief Go to sleep in the deepest allowed mode + * + * Searches through the sleep mode lock counts, starting at the shallowest sleep + * mode, until the first non-zero lock count is found. The device is then put to + * sleep in the sleep mode that corresponds to the lock. + * + * \note This function enables interrupts before going to sleep, and will leave + * them enabled upon return. This also applies if sleep is skipped due to ACTIVE + * mode being locked. + */ + +static inline void sleepmgr_enter_sleep(void) +{ +#ifdef CONFIG_SLEEPMGR_ENABLE + enum sleepmgr_mode sleep_mode; + + cpu_irq_disable(); + + // Find the deepest allowable sleep mode + sleep_mode = sleepmgr_get_sleep_mode(); + // Return right away if first mode (ACTIVE) is locked. + if (sleep_mode==SLEEPMGR_ACTIVE) { + cpu_irq_enable(); + return; + } + // Enter the deepest allowable sleep mode with interrupts enabled + sleepmgr_sleep(sleep_mode); +#else + cpu_irq_enable(); +#endif /* CONFIG_SLEEPMGR_ENABLE */ +} + + +//! @} + +#endif /* SLEEPMGR_H */ diff --git a/DSTAT-temp/src/asf/common/services/sleepmgr/xmega/sleepmgr.c b/DSTAT-temp/src/asf/common/services/sleepmgr/xmega/sleepmgr.c new file mode 100644 index 0000000..658666a --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/sleepmgr/xmega/sleepmgr.c @@ -0,0 +1,58 @@ +/** + * \file + * + * \brief Sleep manager + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include +#include + +#if defined(CONFIG_SLEEPMGR_ENABLE) || defined(__DOXYGEN__) + +uint8_t sleepmgr_locks[SLEEPMGR_NR_OF_MODES]; + +enum SLEEP_SMODE_enum sleepmgr_configs[SLEEPMGR_NR_OF_MODES] = { + SLEEP_SMODE_IDLE_gc, + SLEEP_SMODE_ESTDBY_gc, + SLEEP_SMODE_PSAVE_gc, + SLEEP_SMODE_STDBY_gc, + SLEEP_SMODE_PDOWN_gc, +}; + +#endif /* CONFIG_SLEEPMGR_ENABLE */ diff --git a/DSTAT-temp/src/asf/common/services/sleepmgr/xmega/sleepmgr.h b/DSTAT-temp/src/asf/common/services/sleepmgr/xmega/sleepmgr.h new file mode 100644 index 0000000..e50fab9 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/sleepmgr/xmega/sleepmgr.h @@ -0,0 +1,114 @@ +/** + * \file + * + * \brief AVR XMEGA Sleep manager implementation + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef XMEGA_SLEEPMGR_H +#define XMEGA_SLEEPMGR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/** + * \weakgroup sleepmgr_group + * @{ + */ + +enum sleepmgr_mode { + //! Active mode. + SLEEPMGR_ACTIVE = 0, + //! Idle mode. + SLEEPMGR_IDLE, + //! Extended Standby mode. + SLEEPMGR_ESTDBY, + //! Power Save mode. + SLEEPMGR_PSAVE, + //! Standby mode. + SLEEPMGR_STDBY, + //! Power Down mode. + SLEEPMGR_PDOWN, + SLEEPMGR_NR_OF_MODES, +}; + +/** + * \internal + * \name Internal arrays + * @{ + */ +#if defined(CONFIG_SLEEPMGR_ENABLE) || defined(__DOXYGEN__) +//! Sleep mode lock counters +extern uint8_t sleepmgr_locks[]; +/** + * \brief Look-up table with sleep mode configurations + * \note This is located in program memory (Flash) as it is constant. + */ +extern enum SLEEP_SMODE_enum sleepmgr_configs[]; +#endif /* CONFIG_SLEEPMGR_ENABLE */ +//! @} + +static inline void sleepmgr_sleep(const enum sleepmgr_mode sleep_mode) +{ + Assert(sleep_mode != SLEEPMGR_ACTIVE); +#ifdef CONFIG_SLEEPMGR_ENABLE + sleep_set_mode(sleepmgr_configs[sleep_mode-1]); + sleep_enable(); + + cpu_irq_enable(); + sleep_enter(); + + sleep_disable(); +#else + cpu_irq_enable(); +#endif /* CONFIG_SLEEPMGR_ENABLE */ + +} + +//! @} + +#ifdef __cplusplus +} +#endif + +#endif /* XMEGA_SLEEPMGR_H */ diff --git a/DSTAT-temp/src/asf/common/services/spi/usart_spi.h b/DSTAT-temp/src/asf/common/services/spi/usart_spi.h new file mode 100644 index 0000000..af9a20d --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/spi/usart_spi.h @@ -0,0 +1,99 @@ +/** + * \file + * + * \brief USART in SPI mode driver functions. + * + * Copyright (c) 2010 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef USART_SPI_H_INCLUDED +#define USART_SPI_H_INCLUDED + +#include + +#if XMEGA +# include "xmega_usart_spi/usart_spi.h" +#elif (defined(__GNUC__) && defined(__AVR32__)) || (defined(__ICCAVR32__) || defined(__AAVR32__)) +# include "uc3_usart_spi/usart_spi.h" +#elif SAM +# include "sam_usart_spi/usart_spi.h" +#else +# error Unsupported chip type +#endif + +/** + * + * \defgroup usart_spi_group USART in SPI (Serial Peripheral Interface) mode + * + * This is the common API for USART in SPI mode. Additional features are available + * in the documentation of the specific modules. + * + * \section spi_group_platform Platform Dependencies + * + * The spi API is partially chip- or platform-specific. While all + * platforms provide mostly the same functionality, there are some + * variations around how different bus types and clock tree structures + * are handled. + * + * The following functions are available on all platforms, but there may + * be variations in the function signature (i.e. parameters) and + * behaviour. These functions are typically called by platform-specific + * parts of drivers, and applications that aren't intended to be + * portable: + * - usart_spi_init() + * - usart_spi_setup_device() + * - usart_spi_select_device() + * - usart_spi_deselect_device() + * - usart_spi_write_single() + * - usart_spi_write_packet() + * - usart_spi_read_single() + * - usart_spi_read_packet() + * - usart_spi_is_tx_empty() + * - usart_spi_is_tx_ready() + * - usart_spi_is_rx_full() + * - usart_spi_is_rx_ready() + * - usart_spi_enable() + * - usart_spi_disable() + * - usart_spi_is_enabled() + * + * + * @{ + */ + +//! @} + +#endif /* USART_SPI_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/common/services/spi/xmega_usart_spi/usart_spi.c b/DSTAT-temp/src/asf/common/services/spi/xmega_usart_spi/usart_spi.c new file mode 100644 index 0000000..b099f2c --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/spi/xmega_usart_spi/usart_spi.c @@ -0,0 +1,137 @@ +/** + * \file + * + * \brief AVR XMEGA USART in SPI mode driver functions. + * + * Copyright (c) 2010 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include "usart_spi.h" +#include "sysclk.h" + +void usart_spi_init(USART_t *usart) +{ +#ifdef USARTC0 + if((uint16_t)usart == (uint16_t)&USARTC0) { + sysclk_enable_module(SYSCLK_PORT_C,PR_USART0_bm); + } +#endif +#ifdef USARTC1 + else + if((uint16_t)usart == (uint16_t)&USARTC1) { + sysclk_enable_module(SYSCLK_PORT_C,PR_USART1_bm); + } +#endif +#ifdef USARTD0 + else + if((uint16_t)usart == (uint16_t)&USARTD0) { + sysclk_enable_module(SYSCLK_PORT_D,PR_USART0_bm); + } +#endif +#ifdef USARTD1 + else + if((uint16_t)usart == (uint16_t)&USARTD1) { + sysclk_enable_module(SYSCLK_PORT_D,PR_USART1_bm); + } +#endif +#ifdef USARTE0 + else + if((uint16_t)usart == (uint16_t)&USARTE0) { + sysclk_enable_module(SYSCLK_PORT_E,PR_USART0_bm); + } +#endif +#ifdef USARTE1 + else + if((uint16_t)usart == (uint16_t)&USARTE1) { + sysclk_enable_module(SYSCLK_PORT_E,PR_USART1_bm); + } +#endif +#ifdef USARTF0 + else + if((uint16_t)usart == (uint16_t)&USARTF0) { + sysclk_enable_module(SYSCLK_PORT_F,PR_USART0_bm); + } +#endif +#ifdef USARTF1 + else + if((uint16_t)usart == (uint16_t)&USARTF1) { + sysclk_enable_module(SYSCLK_PORT_F,PR_USART1_bm); + } +#endif +} + +void usart_spi_setup_device(USART_t *usart, struct usart_spi_device *device, + spi_flags_t flags, unsigned long baud_rate, + board_spi_select_id_t sel_id) +{ + usart_spi_options_t opt; + opt.baudrate=baud_rate; + opt.spimode=flags; + opt.data_order=false; + usart_init_spi(usart, &opt); +} + +status_code_t usart_spi_write_packet(USART_t *usart,const uint8_t *data, size_t len) +{ + size_t i=0; + while(len) { + usart_spi_transmit(usart,*(data+i)); + len--; + i++; + } + return STATUS_OK; +} + +status_code_t usart_spi_read_packet(USART_t *usart, uint8_t *data, size_t len) +{ + while(len) { + *data = usart_spi_transmit(usart, CONFIG_USART_SPI_DUMMY); + len--; + data++; + } + return STATUS_OK; +} + +void usart_spi_select_device(USART_t *usart, struct usart_spi_device *device) +{ + ioport_set_pin_low(device->id); +} + +void usart_spi_deselect_device(USART_t *usart, struct usart_spi_device *device) +{ + ioport_set_pin_high(device->id); +} diff --git a/DSTAT-temp/src/asf/common/services/spi/xmega_usart_spi/usart_spi.h b/DSTAT-temp/src/asf/common/services/spi/xmega_usart_spi/usart_spi.h new file mode 100644 index 0000000..0824830 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/spi/xmega_usart_spi/usart_spi.h @@ -0,0 +1,239 @@ +/** + * \file + * + * \brief AVR XMEGA USART in SPI mode driver functions. + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _USART_SPI_H_ +#define _USART_SPI_H_ + +#include "compiler.h" +#include "status_codes.h" +#include "ioport.h" +#include "usart.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \name USART in SPI mode Management Configuration + */ +//! @{ +#include "conf_usart_spi.h" + +//! Default Config Spi Master Dummy Field +#ifndef CONFIG_USART_SPI_DUMMY + #define CONFIG_USART_SPI_DUMMY 0xFF +#endif +//! @} + +/** + * \brief Clock phase + */ +#define SPI_CPHA (1 << 0) + +/** + * \brief Clock polarity + */ +#define SPI_CPOL (1 << 1) + +/** + * \brief SPI mode 0 + */ +#define SPI_MODE_0 0 +/** + * \brief SPI mode 1 + */ +#define SPI_MODE_1 (SPI_CPHA) +/** + * \brief SPI mode 2 + */ +#define SPI_MODE_2 (SPI_CPOL) +/** + * \brief SPI mode 3 + */ +#define SPI_MODE_3 (SPI_CPOL | SPI_CPHA) + +typedef uint8_t spi_flags_t; +typedef uint32_t board_spi_select_id_t; + +//! \brief Polled SPI device definition +struct usart_spi_device { + //! Board specific select id + port_pin_t id; +}; + +/*! \brief Initializes the USART in SPI master mode. + * + * \param usart Base address of the USART instance. + * + */ +extern void usart_spi_init(USART_t *usart); + +/** + * \brief Setup a USART in SPI mode device. + * + * The returned device descriptor structure must be passed to the driver + * whenever that device should be used as current slave device. + * + * \param usart Base address of the USART instance. + * \param device Pointer to usart device struct that should be initialized. + * \param flags USART configuration flags. Common flags for all + * implementations are the usart modes SPI_MODE_0 ... + * SPI_MODE_3. + * \param baud_rate Baud rate for communication with slave device in Hz. + * \param sel_id Board specific select id + */ +extern void usart_spi_setup_device(USART_t *usart, struct usart_spi_device *device, + spi_flags_t flags, unsigned long baud_rate, + board_spi_select_id_t sel_id); + +/*! \brief Enables the USART for the specified USART in SPI mode. + * + * \param usart Base address of the USART instance. + */ +extern void usart_spi_enable(USART_t *usart); + +/*! \brief Disables the USART. + * + * Ensures that nothing is transferred while setting up buffers. + * + * \param usart Base address of the USART instance. + * + */ +extern void usart_spi_disable(USART_t *usart); + + +/*! \brief Tests if the USART in SPI mode is enabled. + * + * \param usart Base address of the usart instance. + * + * \return \c 1 if the usart is enabled, otherwise \c 0. + */ +extern bool usart_spi_is_enabled(USART_t *usart); + +/** + * \brief Select given device on the SPI bus + * + * Set device specific setting and calls board chip select. + * + * \param usart Base address of the USART instance. + * \param device SPI device + * + */ +extern void usart_spi_select_device(USART_t *usart, struct usart_spi_device *device); + +/** + * \brief Deselect given device on the SPI bus + * + * Calls board chip deselect. + * + * \param usart Base address of the USART instance. + * \param device SPI device + * + * \pre SPI device must be selected with spi_select_device() first + */ +extern void usart_spi_deselect_device(USART_t *usart, struct usart_spi_device *device); + +/*! \brief Write one byte to a SPI device using USART in SPI mode + * + * \param usart Base address of the usart instance. + * \param data The data byte to be loaded + * + */ +__always_inline static void usart_spi_write_single(USART_t *usart, uint8_t data) +{ + usart_putchar(usart,data); +} + +/** + * \brief Send a sequence of bytes to a SPI device using USART in SPI mode + * + * Received bytes on the USART in SPI mode are discarded. + * + * \param usart Base address of the USART instance. + * \param data Data buffer to write + * \param len Length of data + * + * \pre usart device must be selected with spi_select_device() first + */ +extern status_code_t usart_spi_write_packet(USART_t *usart,const uint8_t *data, size_t len); + + +/*! \brief Receive one byte from a SPI device using USART in SPI mode + * + * \param usart Base address of the USART instance. + * \param data Pointer to the data byte where to store the received data. + * + */ +inline static void usart_spi_read_single(USART_t *usart, uint8_t *data) +{ + *data = usart_getchar(usart); +} + +/** + * \brief Receive a sequence of bytes from a USART in SPI mode device + * + * All bytes sent out on usart bus are sent as value 0. + * + * \param usart Base address of the usart instance. + * \param data data buffer to read + * \param len Length of data + * + * \pre usart device must be selected with spi_select_device() first + */ +extern status_code_t usart_spi_read_packet(USART_t *usart, uint8_t *data, size_t len); + +/*! \brief Tests if the USART in SPI mode contains a received character. + * + * \param usart Base address of the USART instance. + * + * \return \c 1 if the USART Receive Holding Register is full, otherwise \c 0. + */ +inline static bool usart_spi_is_rx_full(USART_t *usart) +{ + return usart_rx_is_complete(usart); +} + +#ifdef __cplusplus +} +#endif + +#endif // _USART_SPI_H_ diff --git a/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc.c b/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc.c new file mode 100644 index 0000000..9f71bfe --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc.c @@ -0,0 +1,1037 @@ +/** + * \file + * + * \brief USB Device Communication Device Class (CDC) interface. + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#include "conf_usb.h" +#include "usb_protocol.h" +#include "usb_protocol_cdc.h" +#include "udd.h" +#include "udc.h" +#include "udi_cdc.h" +#include + +#ifdef UDI_CDC_LOW_RATE +# ifdef USB_DEVICE_HS_SUPPORT +# define UDI_CDC_TX_BUFFERS (UDI_CDC_DATA_EPS_HS_SIZE) +# define UDI_CDC_RX_BUFFERS (UDI_CDC_DATA_EPS_HS_SIZE) +# else +# define UDI_CDC_TX_BUFFERS (UDI_CDC_DATA_EPS_FS_SIZE) +# define UDI_CDC_RX_BUFFERS (UDI_CDC_DATA_EPS_FS_SIZE) +# endif +#else +# ifdef USB_DEVICE_HS_SUPPORT +# define UDI_CDC_TX_BUFFERS (UDI_CDC_DATA_EPS_HS_SIZE) +# define UDI_CDC_RX_BUFFERS (UDI_CDC_DATA_EPS_HS_SIZE) +# else +# define UDI_CDC_TX_BUFFERS (5*UDI_CDC_DATA_EPS_FS_SIZE) +# define UDI_CDC_RX_BUFFERS (5*UDI_CDC_DATA_EPS_FS_SIZE) +# endif +#endif + +/** + * \ingroup udi_cdc_group + * \defgroup udi_cdc_group_udc Interface with USB Device Core (UDC) + * + * Structures and functions required by UDC. + * + * @{ + */ +bool udi_cdc_comm_enable(void); +void udi_cdc_comm_disable(void); +bool udi_cdc_comm_setup(void); +bool udi_cdc_data_enable(void); +void udi_cdc_data_disable(void); +bool udi_cdc_data_setup(void); +uint8_t udi_cdc_getsetting(void); +void udi_cdc_data_sof_notify(void); +UDC_DESC_STORAGE udi_api_t udi_api_cdc_comm = { + .enable = udi_cdc_comm_enable, + .disable = udi_cdc_comm_disable, + .setup = udi_cdc_comm_setup, + .getsetting = udi_cdc_getsetting, +}; +UDC_DESC_STORAGE udi_api_t udi_api_cdc_data = { + .enable = udi_cdc_data_enable, + .disable = udi_cdc_data_disable, + .setup = udi_cdc_data_setup, + .getsetting = udi_cdc_getsetting, + .sof_notify = udi_cdc_data_sof_notify, +}; +//@} + +/** + * \ingroup udi_cdc_group + * \defgroup udi_cdc_group_internal Implementation of UDI CDC + * + * Class internal implementation + * @{ + */ + +/** + * \name Internal routines + */ +//@{ + +/** + * \name Routines to control serial line + */ +//@{ + +/** + * \brief Returns the port number corresponding at current setup request + * + * \return port number + */ +static uint8_t udi_cdc_setup_to_port(void); + +/** + * \brief Sends line coding to application + * + * Called after SETUP request when line coding data is received. + */ +static void udi_cdc_line_coding_received(void); + +/** + * \brief Records new state + * + * \param port Communication port number to manage + * \param b_set State is enabled if true, else disabled + * \param bit_mask Field to process (see CDC_SERIAL_STATE_ defines) + */ +static void udi_cdc_ctrl_state_change(uint8_t port, bool b_set, le16_t bit_mask); + +/** + * \brief Check and eventually notify the USB host of new state + * + * \param port Communication port number to manage + * \param ep Port communication endpoint + */ +static void udi_cdc_ctrl_state_notify(uint8_t port, udd_ep_id_t ep); + +/** + * \brief Ack sent of serial state message + * Callback called after serial state message sent + * + * \param status UDD_EP_TRANSFER_OK, if transfer finished + * \param status UDD_EP_TRANSFER_ABORT, if transfer aborted + * \param n number of data transfered + */ +static void udi_cdc_serial_state_msg_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep); + +//@} + +/** + * \name Routines to process data transfer + */ +//@{ + +/** + * \brief Enable the reception of data from the USB host + * + * The value udi_cdc_rx_trans_sel indicate the RX buffer to fill. + * + * \param port Communication port number to manage + * + * \return \c 1 if function was successfully done, otherwise \c 0. + */ +static bool udi_cdc_rx_start(uint8_t port); + +/** + * \brief Update rx buffer management with a new data + * Callback called after data reception on USB line + * + * \param status UDD_EP_TRANSFER_OK, if transfer finish + * \param status UDD_EP_TRANSFER_ABORT, if transfer aborted + * \param n number of data received + */ +static void udi_cdc_data_received(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep); + +/** + * \brief Ack sent of tx buffer + * Callback called after data transfer on USB line + * + * \param status UDD_EP_TRANSFER_OK, if transfer finished + * \param status UDD_EP_TRANSFER_ABORT, if transfer aborted + * \param n number of data transfered + */ +static void udi_cdc_data_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep); + +/** + * \brief Send buffer on line or wait a SOF event + * + * \param port Communication port number to manage + */ +static void udi_cdc_tx_send(uint8_t port); + +//@} + +//@} + +/** + * \name Information about configuration of communication line + */ +//@{ +static usb_cdc_line_coding_t udi_cdc_line_coding[UDI_CDC_PORT_NB]; +static bool udi_cdc_serial_state_msg_ongoing[UDI_CDC_PORT_NB]; +static volatile le16_t udi_cdc_state[UDI_CDC_PORT_NB]; +COMPILER_WORD_ALIGNED static usb_cdc_notify_serial_state_t uid_cdc_state_msg[UDI_CDC_PORT_NB]; + +//! Status of CDC COMM interfaces +static volatile uint8_t udi_cdc_nb_comm_enabled = 0; +//@} + +/** + * \name Variables to manage RX/TX transfer requests + * Two buffers for each sense are used to optimize the speed. + */ +//@{ + +//! Status of CDC DATA interfaces +static volatile uint8_t udi_cdc_nb_data_enabled = 0; +static volatile bool udi_cdc_data_running = false; +//! Buffer to receive data +COMPILER_WORD_ALIGNED static uint8_t udi_cdc_rx_buf[UDI_CDC_PORT_NB][2][UDI_CDC_RX_BUFFERS]; +//! Data available in RX buffers +static uint16_t udi_cdc_rx_buf_nb[UDI_CDC_PORT_NB][2]; +//! Give the current RX buffer used (rx0 if 0, rx1 if 1) +static volatile uint8_t udi_cdc_rx_buf_sel[UDI_CDC_PORT_NB]; +//! Read position in current RX buffer +static volatile uint16_t udi_cdc_rx_pos[UDI_CDC_PORT_NB]; +//! Signal a transfer on-going +static volatile bool udi_cdc_rx_trans_ongoing[UDI_CDC_PORT_NB]; + +//! Define a transfer halted +#define UDI_CDC_TRANS_HALTED 2 + +//! Buffer to send data +COMPILER_WORD_ALIGNED static uint8_t udi_cdc_tx_buf[UDI_CDC_PORT_NB][2][UDI_CDC_TX_BUFFERS]; +//! Data available in TX buffers +static uint16_t udi_cdc_tx_buf_nb[UDI_CDC_PORT_NB][2]; +//! Give current TX buffer used (tx0 if 0, tx1 if 1) +static volatile uint8_t udi_cdc_tx_buf_sel[UDI_CDC_PORT_NB]; +//! Value of SOF during last TX transfer +static uint16_t udi_cdc_tx_sof_num[UDI_CDC_PORT_NB]; +//! Signal a transfer on-going +static volatile bool udi_cdc_tx_trans_ongoing[UDI_CDC_PORT_NB]; +//! Signal that both buffer content data to send +static volatile bool udi_cdc_tx_both_buf_to_send[UDI_CDC_PORT_NB]; + +//@} + +bool udi_cdc_comm_enable(void) +{ + uint8_t port; + uint8_t iface_comm_num; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; + udi_cdc_nb_comm_enabled = 0; +#else + if (udi_cdc_nb_comm_enabled > UDI_CDC_PORT_NB) { + udi_cdc_nb_comm_enabled = 0; + } + port = udi_cdc_nb_comm_enabled; +#endif + + // Initialize control signal management + udi_cdc_state[port] = CPU_TO_LE16(0); + + uid_cdc_state_msg[port].header.bmRequestType = + USB_REQ_DIR_IN | USB_REQ_TYPE_CLASS | + USB_REQ_RECIP_INTERFACE; + uid_cdc_state_msg[port].header.bNotification = USB_REQ_CDC_NOTIFY_SERIAL_STATE; + uid_cdc_state_msg[port].header.wValue = LE16(0); + + switch (port) { +#define UDI_CDC_PORT_TO_IFACE_COMM(index, unused) \ + case index: \ + iface_comm_num = UDI_CDC_COMM_IFACE_NUMBER_##index; \ + break; + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_PORT_TO_IFACE_COMM, ~) +#undef UDI_CDC_PORT_TO_IFACE_COMM + default: + iface_comm_num = UDI_CDC_COMM_IFACE_NUMBER_0; + break; + } + + uid_cdc_state_msg[port].header.wIndex = LE16(iface_comm_num); + uid_cdc_state_msg[port].header.wLength = LE16(2); + uid_cdc_state_msg[port].value = CPU_TO_LE16(0); + + udi_cdc_line_coding[port].dwDTERate = CPU_TO_LE32(UDI_CDC_DEFAULT_RATE); + udi_cdc_line_coding[port].bCharFormat = UDI_CDC_DEFAULT_STOPBITS; + udi_cdc_line_coding[port].bParityType = UDI_CDC_DEFAULT_PARITY; + udi_cdc_line_coding[port].bDataBits = UDI_CDC_DEFAULT_DATABITS; + // Call application callback + // to initialize memories or indicate that interface is enabled + UDI_CDC_SET_CODING_EXT(port,(&udi_cdc_line_coding[port])); + if (!UDI_CDC_ENABLE_EXT(port)) { + return false; + } + udi_cdc_nb_comm_enabled++; + return true; +} + +bool udi_cdc_data_enable(void) +{ + uint8_t port; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; + udi_cdc_nb_data_enabled = 0; +#else + if (udi_cdc_nb_data_enabled > UDI_CDC_PORT_NB) { + udi_cdc_nb_data_enabled = 0; + } + port = udi_cdc_nb_data_enabled; +#endif + + // Initialize TX management + udi_cdc_tx_trans_ongoing[port] = false; + udi_cdc_tx_both_buf_to_send[port] = false; + udi_cdc_tx_buf_sel[port] = 0; + udi_cdc_tx_buf_nb[port][0] = 0; + udi_cdc_tx_buf_nb[port][1] = 0; + udi_cdc_tx_sof_num[port] = 0; + udi_cdc_tx_send(port); + + // Initialize RX management + udi_cdc_rx_trans_ongoing[port] = false; + udi_cdc_rx_buf_sel[port] = 0; + udi_cdc_rx_buf_nb[port][0] = 0; + udi_cdc_rx_pos[port] = 0; + if (!udi_cdc_rx_start(port)) { + return false; + } + udi_cdc_nb_data_enabled++; + if (udi_cdc_nb_data_enabled == UDI_CDC_PORT_NB) { + udi_cdc_data_running = true; + } + return true; +} + +void udi_cdc_comm_disable(void) +{ + Assert(udi_cdc_nb_comm_enabled != 0); + udi_cdc_nb_comm_enabled--; +} + +void udi_cdc_data_disable(void) +{ + uint8_t port; + + Assert(udi_cdc_nb_data_enabled != 0); + udi_cdc_nb_data_enabled--; + port = udi_cdc_nb_data_enabled; + UDI_CDC_DISABLE_EXT(port); + udi_cdc_data_running = false; +} + +bool udi_cdc_comm_setup(void) +{ + uint8_t port = udi_cdc_setup_to_port(); + + if (Udd_setup_is_in()) { + // GET Interface Requests + if (Udd_setup_type() == USB_REQ_TYPE_CLASS) { + // Requests Class Interface Get + switch (udd_g_ctrlreq.req.bRequest) { + case USB_REQ_CDC_GET_LINE_CODING: + // Get configuration of CDC line + if (sizeof(usb_cdc_line_coding_t) != + udd_g_ctrlreq.req.wLength) + return false; // Error for USB host + udd_g_ctrlreq.payload = + (uint8_t *) & + udi_cdc_line_coding[port]; + udd_g_ctrlreq.payload_size = + sizeof(usb_cdc_line_coding_t); + return true; + } + } + } + if (Udd_setup_is_out()) { + // SET Interface Requests + if (Udd_setup_type() == USB_REQ_TYPE_CLASS) { + // Requests Class Interface Set + switch (udd_g_ctrlreq.req.bRequest) { + case USB_REQ_CDC_SET_LINE_CODING: + // Change configuration of CDC line + if (sizeof(usb_cdc_line_coding_t) != + udd_g_ctrlreq.req.wLength) + return false; // Error for USB host + udd_g_ctrlreq.callback = + udi_cdc_line_coding_received; + udd_g_ctrlreq.payload = + (uint8_t *) & + udi_cdc_line_coding[port]; + udd_g_ctrlreq.payload_size = + sizeof(usb_cdc_line_coding_t); + return true; + case USB_REQ_CDC_SET_CONTROL_LINE_STATE: + // According cdc spec 1.1 chapter 6.2.14 + UDI_CDC_SET_DTR_EXT(port, (0 != + (udd_g_ctrlreq.req.wValue + & CDC_CTRL_SIGNAL_DTE_PRESENT))); + UDI_CDC_SET_RTS_EXT(port, (0 != + (udd_g_ctrlreq.req.wValue + & CDC_CTRL_SIGNAL_ACTIVATE_CARRIER))); + return true; + } + } + } + return false; // request Not supported +} + +bool udi_cdc_data_setup(void) +{ + return false; // request Not supported +} + +uint8_t udi_cdc_getsetting(void) +{ + return 0; // CDC don't have multiple alternate setting +} + +void udi_cdc_data_sof_notify(void) +{ + static uint8_t port_notify = 0; + + // A call of udi_cdc_data_sof_notify() is done for each port + udi_cdc_tx_send(port_notify); +#if UDI_CDC_PORT_NB != 1 // To optimize code + port_notify++; + if (port_notify >= UDI_CDC_PORT_NB) { + port_notify = 0; + } +#endif +} + + +//------------------------------------------------- +//------- Internal routines to control serial line + +static uint8_t udi_cdc_setup_to_port(void) +{ + uint8_t port; + + switch (udd_g_ctrlreq.req.wIndex & 0xFF) { +#define UDI_CDC_IFACE_COMM_TO_PORT(iface, unused) \ + case UDI_CDC_COMM_IFACE_NUMBER_##iface: \ + port = iface; \ + break; + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_IFACE_COMM_TO_PORT, ~) +#undef UDI_CDC_IFACE_COMM_TO_PORT + default: + port = 0; + break; + } + return port; +} + +static void udi_cdc_line_coding_received(void) +{ + uint8_t port = udi_cdc_setup_to_port(); + UDI_CDC_SET_CODING_EXT(port, (&udi_cdc_line_coding[port])); +} + +static void udi_cdc_ctrl_state_change(uint8_t port, bool b_set, le16_t bit_mask) +{ + irqflags_t flags; + udd_ep_id_t ep_comm; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + + // Update state + flags = cpu_irq_save(); // Protect udi_cdc_state + if (b_set) { + udi_cdc_state[port] |= bit_mask; + } else { + udi_cdc_state[port] &= ~(unsigned)bit_mask; + } + cpu_irq_restore(flags); + + // Send it if possible and state changed + switch (port) { +#define UDI_CDC_PORT_TO_COMM_EP(index, unused) \ + case index: \ + ep_comm = UDI_CDC_COMM_EP_##index; \ + break; + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_PORT_TO_COMM_EP, ~) +#undef UDI_CDC_PORT_TO_COMM_EP + default: + ep_comm = UDI_CDC_COMM_EP_0; + break; + } + udi_cdc_ctrl_state_notify(port, ep_comm); +} + + +static void udi_cdc_ctrl_state_notify(uint8_t port, udd_ep_id_t ep) +{ +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + + // Send it if possible and state changed + if ((!udi_cdc_serial_state_msg_ongoing[port]) + && (udi_cdc_state[port] != uid_cdc_state_msg[port].value)) { + // Fill notification message + uid_cdc_state_msg[port].value = udi_cdc_state[port]; + // Send notification message + udi_cdc_serial_state_msg_ongoing[port] = + udd_ep_run(ep, + false, + (uint8_t *) & uid_cdc_state_msg[port], + sizeof(uid_cdc_state_msg[0]), + udi_cdc_serial_state_msg_sent); + } +} + + +static void udi_cdc_serial_state_msg_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep) +{ + uint8_t port; + UNUSED(n); + UNUSED(status); + + switch (ep) { +#define UDI_CDC_GET_PORT_FROM_COMM_EP(iface, unused) \ + case UDI_CDC_COMM_EP_##iface: \ + port = iface; \ + break; + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_GET_PORT_FROM_COMM_EP, ~) +#undef UDI_CDC_GET_PORT_FROM_COMM_EP + default: + port = 0; + break; + } + + udi_cdc_serial_state_msg_ongoing[port] = false; + + // For the irregular signals like break, the incoming ring signal, + // or the overrun error state, this will reset their values to zero + // and again will not send another notification until their state changes. + udi_cdc_state[port] &= ~(CDC_SERIAL_STATE_BREAK | + CDC_SERIAL_STATE_RING | + CDC_SERIAL_STATE_FRAMING | + CDC_SERIAL_STATE_PARITY | CDC_SERIAL_STATE_OVERRUN); + uid_cdc_state_msg[port].value &= ~(CDC_SERIAL_STATE_BREAK | + CDC_SERIAL_STATE_RING | + CDC_SERIAL_STATE_FRAMING | + CDC_SERIAL_STATE_PARITY | CDC_SERIAL_STATE_OVERRUN); + // Send it if possible and state changed + udi_cdc_ctrl_state_notify(port, ep); +} + + +//------------------------------------------------- +//------- Internal routines to process data transfer + + +static bool udi_cdc_rx_start(uint8_t port) +{ + irqflags_t flags; + uint8_t buf_sel_trans; + udd_ep_id_t ep; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + + flags = cpu_irq_save(); + buf_sel_trans = udi_cdc_rx_buf_sel[port]; + if (udi_cdc_rx_trans_ongoing[port] || + (udi_cdc_rx_pos[port] < udi_cdc_rx_buf_nb[port][buf_sel_trans])) { + // Transfer already on-going or current buffer no empty + cpu_irq_restore(flags); + return false; + } + + // Change current buffer + udi_cdc_rx_pos[port] = 0; + udi_cdc_rx_buf_sel[port] = (buf_sel_trans==0)?1:0; + + // Start transfer on RX + udi_cdc_rx_trans_ongoing[port] = true; + cpu_irq_restore(flags); + + if (udi_cdc_multi_is_rx_ready(port)) { + UDI_CDC_RX_NOTIFY(port); + } + // Send the buffer with enable of short packet + switch (port) { +#define UDI_CDC_PORT_TO_DATA_EP_OUT(index, unused) \ + case index: \ + ep = UDI_CDC_DATA_EP_OUT_##index; \ + break; + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_PORT_TO_DATA_EP_OUT, ~) +#undef UDI_CDC_PORT_TO_DATA_EP_OUT + default: + ep = UDI_CDC_DATA_EP_OUT_0; + break; + } + return udd_ep_run(ep, + true, + udi_cdc_rx_buf[port][buf_sel_trans], + UDI_CDC_RX_BUFFERS, + udi_cdc_data_received); +} + + +static void udi_cdc_data_received(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep) +{ + uint8_t buf_sel_trans; + uint8_t port; + + switch (ep) { +#define UDI_CDC_DATA_EP_OUT_TO_PORT(index, unused) \ + case UDI_CDC_DATA_EP_OUT_##index: \ + port = index; \ + break; + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_DATA_EP_OUT_TO_PORT, ~) +#undef UDI_CDC_DATA_EP_OUT_TO_PORT + default: + port = 0; + break; + } + + if (UDD_EP_TRANSFER_OK != status) { + // Abort reception + return; + } + buf_sel_trans = (udi_cdc_rx_buf_sel[port]==0)?1:0; + if (!n) { + udd_ep_run( ep, + true, + udi_cdc_rx_buf[port][buf_sel_trans], + UDI_CDC_RX_BUFFERS, + udi_cdc_data_received); + return; + } + udi_cdc_rx_buf_nb[port][buf_sel_trans] = n; + udi_cdc_rx_trans_ongoing[port] = false; + udi_cdc_rx_start(port); +} + + +static void udi_cdc_data_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep) +{ + uint8_t port; + UNUSED(n); + + switch (ep) { +#define UDI_CDC_DATA_EP_IN_TO_PORT(index, unused) \ + case UDI_CDC_DATA_EP_IN_##index: \ + port = index; \ + break; + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_DATA_EP_IN_TO_PORT, ~) +#undef UDI_CDC_DATA_EP_IN_TO_PORT + default: + port = 0; + break; + } + + if (UDD_EP_TRANSFER_OK != status) { + // Abort transfer + return; + } + udi_cdc_tx_buf_nb[port][(udi_cdc_tx_buf_sel[port]==0)?1:0] = 0; + udi_cdc_tx_both_buf_to_send[port] = false; + udi_cdc_tx_trans_ongoing[port] = false; + udi_cdc_tx_send(port); +} + + +static void udi_cdc_tx_send(uint8_t port) +{ + irqflags_t flags; + uint8_t buf_sel_trans; + bool b_short_packet; + udd_ep_id_t ep; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + + if (udi_cdc_tx_trans_ongoing[port]) { + return; // Already on going or wait next SOF to send next data + } + if (udd_is_high_speed()) { + if (udi_cdc_tx_sof_num[port] == udd_get_micro_frame_number()) { + return; // Wait next SOF to send next data + } + }else{ + if (udi_cdc_tx_sof_num[port] == udd_get_frame_number()) { + return; // Wait next SOF to send next data + } + } + + flags = cpu_irq_save(); // to protect udi_cdc_tx_buf_sel + buf_sel_trans = udi_cdc_tx_buf_sel[port]; + if (!udi_cdc_tx_both_buf_to_send[port]) { + // Send current Buffer + // and switch the current buffer + udi_cdc_tx_buf_sel[port] = (buf_sel_trans==0)?1:0; + }else{ + // Send the other Buffer + // and no switch the current buffer + buf_sel_trans = (buf_sel_trans==0)?1:0; + } + udi_cdc_tx_trans_ongoing[port] = true; + cpu_irq_restore(flags); + + b_short_packet = (udi_cdc_tx_buf_nb[port][buf_sel_trans] != UDI_CDC_TX_BUFFERS); + if (b_short_packet) { + if (udd_is_high_speed()) { + udi_cdc_tx_sof_num[port] = udd_get_micro_frame_number(); + }else{ + udi_cdc_tx_sof_num[port] = udd_get_frame_number(); + } + }else{ + udi_cdc_tx_sof_num[port] = 0; // Force next transfer without wait SOF + } + + // Send the buffer with enable of short packet + switch (port) { +#define UDI_CDC_PORT_TO_DATA_EP_IN(index, unused) \ + case index: \ + ep = UDI_CDC_DATA_EP_IN_##index; \ + break; + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_PORT_TO_DATA_EP_IN, ~) +#undef UDI_CDC_PORT_TO_DATA_EP_IN + default: + ep = UDI_CDC_DATA_EP_IN_0; + break; + } + udd_ep_run( ep, + b_short_packet, + udi_cdc_tx_buf[port][buf_sel_trans], + udi_cdc_tx_buf_nb[port][buf_sel_trans], + udi_cdc_data_sent); +} + + +//--------------------------------------------- +//------- Application interface + + +//------- Application interface + +void udi_cdc_ctrl_signal_dcd(bool b_set) +{ + udi_cdc_ctrl_state_change(0, b_set, CDC_SERIAL_STATE_DCD); +} + +void udi_cdc_ctrl_signal_dsr(bool b_set) +{ + udi_cdc_ctrl_state_change(0, b_set, CDC_SERIAL_STATE_DSR); +} + +void udi_cdc_signal_framing_error(void) +{ + udi_cdc_ctrl_state_change(0, true, CDC_SERIAL_STATE_FRAMING); +} + +void udi_cdc_signal_parity_error(void) +{ + udi_cdc_ctrl_state_change(0, true, CDC_SERIAL_STATE_PARITY); +} + +void udi_cdc_signal_overrun(void) +{ + udi_cdc_ctrl_state_change(0, true, CDC_SERIAL_STATE_OVERRUN); +} + +void udi_cdc_multi_ctrl_signal_dcd(uint8_t port, bool b_set) +{ + udi_cdc_ctrl_state_change(port, b_set, CDC_SERIAL_STATE_DCD); +} + +void udi_cdc_multi_ctrl_signal_dsr(uint8_t port, bool b_set) +{ + udi_cdc_ctrl_state_change(port, b_set, CDC_SERIAL_STATE_DSR); +} + +void udi_cdc_multi_signal_framing_error(uint8_t port) +{ + udi_cdc_ctrl_state_change(port, true, CDC_SERIAL_STATE_FRAMING); +} + +void udi_cdc_multi_signal_parity_error(uint8_t port) +{ + udi_cdc_ctrl_state_change(port, true, CDC_SERIAL_STATE_PARITY); +} + +void udi_cdc_multi_signal_overrun(uint8_t port) +{ + udi_cdc_ctrl_state_change(port, true, CDC_SERIAL_STATE_OVERRUN); +} + +bool udi_cdc_multi_is_rx_ready(uint8_t port) +{ +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + uint16_t pos = udi_cdc_rx_pos[port]; + return (pos < udi_cdc_rx_buf_nb[port][udi_cdc_rx_buf_sel[port]]); +} + +bool udi_cdc_is_rx_ready(void) +{ + return udi_cdc_multi_is_rx_ready(0); +} + +int udi_cdc_multi_getc(uint8_t port) +{ + int rx_data = 0; + bool b_databit_9; + uint16_t pos; + uint8_t buf_sel; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + + b_databit_9 = (9 == udi_cdc_line_coding[port].bDataBits); + +udi_cdc_getc_process_one_byte: + // Check available data + pos = udi_cdc_rx_pos[port]; + buf_sel = udi_cdc_rx_buf_sel[port]; + while (pos >= udi_cdc_rx_buf_nb[port][buf_sel]) { + if (!udi_cdc_data_running) { + return 0; + } + goto udi_cdc_getc_process_one_byte; + } + + // Read data + rx_data |= udi_cdc_rx_buf[port][buf_sel][pos]; + udi_cdc_rx_pos[port] = pos+1; + + udi_cdc_rx_start(port); + + if (b_databit_9) { + // Receive MSB + b_databit_9 = false; + rx_data = rx_data << 8; + goto udi_cdc_getc_process_one_byte; + } + return rx_data; +} + +int udi_cdc_getc(void) +{ + return udi_cdc_multi_getc(0); +} + +iram_size_t udi_cdc_multi_read_buf(uint8_t port, void* buf, iram_size_t size) +{ + uint8_t *ptr_buf = (uint8_t *)buf; + iram_size_t copy_nb; + uint16_t pos; + uint8_t buf_sel; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + +udi_cdc_read_buf_loop_wait: + // Check available data + pos = udi_cdc_rx_pos[port]; + buf_sel = udi_cdc_rx_buf_sel[port]; + while (pos >= udi_cdc_rx_buf_nb[port][buf_sel]) { + if (!udi_cdc_data_running) { + return size; + } + goto udi_cdc_read_buf_loop_wait; + } + + // Read data + copy_nb = udi_cdc_rx_buf_nb[port][buf_sel] - pos; + if (copy_nb>size) { + copy_nb = size; + } + memcpy(ptr_buf, &udi_cdc_rx_buf[port][buf_sel][pos], copy_nb); + udi_cdc_rx_pos[port] += copy_nb; + ptr_buf += copy_nb; + size -= copy_nb; + udi_cdc_rx_start(port); + + if (size) { + goto udi_cdc_read_buf_loop_wait; + } + return 0; +} + +iram_size_t udi_cdc_read_buf(void* buf, iram_size_t size) +{ + return udi_cdc_multi_read_buf(0, buf, size); +} + +bool udi_cdc_multi_is_tx_ready(uint8_t port) +{ + irqflags_t flags; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + + if (udi_cdc_tx_buf_nb[port][udi_cdc_tx_buf_sel[port]]!=UDI_CDC_TX_BUFFERS) { + return true; + } + if (!udi_cdc_tx_both_buf_to_send[port]) { + flags = cpu_irq_save(); // to protect udi_cdc_tx_buf_sel + if (!udi_cdc_tx_trans_ongoing[port]) { + // No transfer on-going + // then use the other buffer to store data + udi_cdc_tx_both_buf_to_send[port] = true; + udi_cdc_tx_buf_sel[port] = (udi_cdc_tx_buf_sel[port]==0)?1:0; + } + cpu_irq_restore(flags); + } + return (udi_cdc_tx_buf_nb[port][udi_cdc_tx_buf_sel[port]]!=UDI_CDC_TX_BUFFERS); +} + +bool udi_cdc_is_tx_ready(void) +{ + return udi_cdc_multi_is_tx_ready(0); +} + +int udi_cdc_multi_putc(uint8_t port, int value) +{ + irqflags_t flags; + bool b_databit_9; + uint8_t buf_sel; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + + b_databit_9 = (9 == udi_cdc_line_coding[port].bDataBits); + +udi_cdc_putc_process_one_byte: + // Check available space + if (!udi_cdc_multi_is_tx_ready(port)) { + if (!udi_cdc_data_running) { + return false; + } + goto udi_cdc_putc_process_one_byte; + } + + // Write value + flags = cpu_irq_save(); + buf_sel = udi_cdc_tx_buf_sel[port]; + udi_cdc_tx_buf[port][buf_sel][udi_cdc_tx_buf_nb[port][buf_sel]++] = value; + cpu_irq_restore(flags); + + if (b_databit_9) { + // Send MSB + b_databit_9 = false; + value = value >> 8; + goto udi_cdc_putc_process_one_byte; + } + return true; +} + +int udi_cdc_putc(int value) +{ + return udi_cdc_multi_putc(0, value); +} + +iram_size_t udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t size) +{ + irqflags_t flags; + uint8_t buf_sel; + uint16_t buf_nb; + iram_size_t copy_nb; + uint8_t *ptr_buf = (uint8_t *)buf; + +#if UDI_CDC_PORT_NB == 1 // To optimize code + port = 0; +#endif + + if (9 == udi_cdc_line_coding[port].bDataBits) { + size *=2; + } + +udi_cdc_write_buf_loop_wait: + // Check available space + if (!udi_cdc_multi_is_tx_ready(port)) { + if (!udi_cdc_data_running) { + return size; + } + goto udi_cdc_write_buf_loop_wait; + } + + // Write values + flags = cpu_irq_save(); + buf_sel = udi_cdc_tx_buf_sel[port]; + buf_nb = udi_cdc_tx_buf_nb[port][buf_sel]; + copy_nb = UDI_CDC_TX_BUFFERS - buf_nb; + if (copy_nb>size) { + copy_nb = size; + } + memcpy(&udi_cdc_tx_buf[port][buf_sel][buf_nb], ptr_buf, copy_nb); + udi_cdc_tx_buf_nb[port][buf_sel] = buf_nb + copy_nb; + cpu_irq_restore(flags); + + // Update buffer pointer + ptr_buf = ptr_buf + copy_nb; + size -= copy_nb; + + if (size) { + goto udi_cdc_write_buf_loop_wait; + } + + return 0; +} + +iram_size_t udi_cdc_write_buf(const void* buf, iram_size_t size) +{ + return udi_cdc_multi_write_buf(0, buf, size); +} + +//@} diff --git a/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc.h b/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc.h new file mode 100644 index 0000000..de7ea7b --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc.h @@ -0,0 +1,764 @@ +/** + * \file + * + * \brief USB Device Communication Device Class (CDC) interface definitions. + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _UDI_CDC_H_ +#define _UDI_CDC_H_ + +#include "conf_usb.h" +#include "usb_protocol.h" +#include "usb_protocol_cdc.h" +#include "udd.h" +#include "udc_desc.h" +#include "udi.h" + +// Check the number of port +#ifndef UDI_CDC_PORT_NB +# define UDI_CDC_PORT_NB 1 +#endif +#if (UDI_CDC_PORT_NB < 1) || (UDI_CDC_PORT_NB > 7) +# error UDI_CDC_PORT_NB must be between 1 and 7 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup udi_cdc_group_udc + * @{ + */ + +//! Global structure which contains standard UDI API for UDC +extern UDC_DESC_STORAGE udi_api_t udi_api_cdc_comm; +extern UDC_DESC_STORAGE udi_api_t udi_api_cdc_data; +//@} + +/** + * \ingroup udi_cdc_group + * \defgroup udi_cdc_group_desc USB interface descriptors + * + * The following structures provide predefined USB interface descriptors. + * It must be used to define the final USB descriptors. + */ +//@{ + +/** + * \brief Communication Class interface descriptor + * + * Interface descriptor with associated functional and endpoint + * descriptors for the CDC Communication Class interface. + */ +typedef struct { + //! Standard interface descriptor + usb_iface_desc_t iface; + //! CDC Header functional descriptor + usb_cdc_hdr_desc_t header; + //! CDC Abstract Control Model functional descriptor + usb_cdc_acm_desc_t acm; + //! CDC Union functional descriptor + usb_cdc_union_desc_t union_desc; + //! CDC Call Management functional descriptor + usb_cdc_call_mgmt_desc_t call_mgmt; + //! Notification endpoint descriptor + usb_ep_desc_t ep_notify; +} udi_cdc_comm_desc_t; + + +/** + * \brief Data Class interface descriptor + * + * Interface descriptor with associated endpoint descriptors for the + * CDC Data Class interface. + */ +typedef struct { + //! Standard interface descriptor + usb_iface_desc_t iface; + //! Data IN/OUT endpoint descriptors + usb_ep_desc_t ep_in; + usb_ep_desc_t ep_out; +} udi_cdc_data_desc_t; + + +//! CDC communication endpoints size for all speeds +#define UDI_CDC_COMM_EP_SIZE 64 +//! CDC data endpoints size for FS speed (8B, 16B, 32B, 64B) +#define UDI_CDC_DATA_EPS_FS_SIZE 64 +//! CDC data endpoints size for HS speed (512B only) +#define UDI_CDC_DATA_EPS_HS_SIZE 512 + +/** + * \name Content of interface descriptors + * Up to 7 CDC interfaces can be implemented on a USB device. + */ +//@{ +//! By default no string associated to these interfaces +#ifndef UDI_CDC_IAD_STRING_ID_0 +#define UDI_CDC_IAD_STRING_ID_0 0 +#endif +#ifndef UDI_CDC_COMM_STRING_ID_0 +#define UDI_CDC_COMM_STRING_ID_0 0 +#endif +#ifndef UDI_CDC_DATA_STRING_ID_0 +#define UDI_CDC_DATA_STRING_ID_0 0 +#endif +#define UDI_CDC_IAD_DESC_0 UDI_CDC_IAD_DESC(0) +#define UDI_CDC_COMM_DESC_0 UDI_CDC_COMM_DESC(0) +#define UDI_CDC_DATA_DESC_0_FS UDI_CDC_DATA_DESC_FS(0) +#define UDI_CDC_DATA_DESC_0_HS UDI_CDC_DATA_DESC_HS(0) + +//! By default no string associated to these interfaces +#ifndef UDI_CDC_IAD_STRING_ID_1 +#define UDI_CDC_IAD_STRING_ID_1 0 +#endif +#ifndef UDI_CDC_COMM_STRING_ID_1 +#define UDI_CDC_COMM_STRING_ID_1 0 +#endif +#ifndef UDI_CDC_DATA_STRING_ID_1 +#define UDI_CDC_DATA_STRING_ID_1 0 +#endif +#define UDI_CDC_IAD_DESC_1 UDI_CDC_IAD_DESC(1) +#define UDI_CDC_COMM_DESC_1 UDI_CDC_COMM_DESC(1) +#define UDI_CDC_DATA_DESC_1_FS UDI_CDC_DATA_DESC_FS(1) +#define UDI_CDC_DATA_DESC_1_HS UDI_CDC_DATA_DESC_HS(1) + +//! By default no string associated to these interfaces +#ifndef UDI_CDC_IAD_STRING_ID_2 +#define UDI_CDC_IAD_STRING_ID_2 0 +#endif +#ifndef UDI_CDC_COMM_STRING_ID_2 +#define UDI_CDC_COMM_STRING_ID_2 0 +#endif +#ifndef UDI_CDC_DATA_STRING_ID_2 +#define UDI_CDC_DATA_STRING_ID_2 0 +#endif +#define UDI_CDC_IAD_DESC_2 UDI_CDC_IAD_DESC(2) +#define UDI_CDC_COMM_DESC_2 UDI_CDC_COMM_DESC(2) +#define UDI_CDC_DATA_DESC_2_FS UDI_CDC_DATA_DESC_FS(2) +#define UDI_CDC_DATA_DESC_2_HS UDI_CDC_DATA_DESC_HS(2) + +//! By default no string associated to these interfaces +#ifndef UDI_CDC_IAD_STRING_ID_3 +#define UDI_CDC_IAD_STRING_ID_3 0 +#endif +#ifndef UDI_CDC_COMM_STRING_ID_3 +#define UDI_CDC_COMM_STRING_ID_3 0 +#endif +#ifndef UDI_CDC_DATA_STRING_ID_3 +#define UDI_CDC_DATA_STRING_ID_3 0 +#endif +#define UDI_CDC_IAD_DESC_3 UDI_CDC_IAD_DESC(3) +#define UDI_CDC_COMM_DESC_3 UDI_CDC_COMM_DESC(3) +#define UDI_CDC_DATA_DESC_3_FS UDI_CDC_DATA_DESC_FS(3) +#define UDI_CDC_DATA_DESC_3_HS UDI_CDC_DATA_DESC_HS(3) + +//! By default no string associated to these interfaces +#ifndef UDI_CDC_IAD_STRING_ID_4 +#define UDI_CDC_IAD_STRING_ID_4 0 +#endif +#ifndef UDI_CDC_COMM_STRING_ID_4 +#define UDI_CDC_COMM_STRING_ID_4 0 +#endif +#ifndef UDI_CDC_DATA_STRING_ID_4 +#define UDI_CDC_DATA_STRING_ID_4 0 +#endif +#define UDI_CDC_IAD_DESC_4 UDI_CDC_IAD_DESC(4) +#define UDI_CDC_COMM_DESC_4 UDI_CDC_COMM_DESC(4) +#define UDI_CDC_DATA_DESC_4_FS UDI_CDC_DATA_DESC_FS(4) +#define UDI_CDC_DATA_DESC_4_HS UDI_CDC_DATA_DESC_HS(4) + +//! By default no string associated to these interfaces +#ifndef UDI_CDC_IAD_STRING_ID_5 +#define UDI_CDC_IAD_STRING_ID_5 0 +#endif +#ifndef UDI_CDC_COMM_STRING_ID_5 +#define UDI_CDC_COMM_STRING_ID_5 0 +#endif +#ifndef UDI_CDC_DATA_STRING_ID_5 +#define UDI_CDC_DATA_STRING_ID_5 0 +#endif +#define UDI_CDC_IAD_DESC_5 UDI_CDC_IAD_DESC(5) +#define UDI_CDC_COMM_DESC_5 UDI_CDC_COMM_DESC(5) +#define UDI_CDC_DATA_DESC_5_FS UDI_CDC_DATA_DESC_FS(5) +#define UDI_CDC_DATA_DESC_5_HS UDI_CDC_DATA_DESC_HS(5) + +//! By default no string associated to these interfaces +#ifndef UDI_CDC_IAD_STRING_ID_6 +#define UDI_CDC_IAD_STRING_ID_6 0 +#endif +#ifndef UDI_CDC_COMM_STRING_ID_6 +#define UDI_CDC_COMM_STRING_ID_6 0 +#endif +#ifndef UDI_CDC_DATA_STRING_ID_6 +#define UDI_CDC_DATA_STRING_ID_6 0 +#endif +#define UDI_CDC_IAD_DESC_6 UDI_CDC_IAD_DESC(6) +#define UDI_CDC_COMM_DESC_6 UDI_CDC_COMM_DESC(6) +#define UDI_CDC_DATA_DESC_6_FS UDI_CDC_DATA_DESC_FS(6) +#define UDI_CDC_DATA_DESC_6_HS UDI_CDC_DATA_DESC_HS(6) +//@} + + +//! Content of CDC IAD interface descriptor for all speeds +#define UDI_CDC_IAD_DESC(port) { \ + .bLength = sizeof(usb_iad_desc_t),\ + .bDescriptorType = USB_DT_IAD,\ + .bInterfaceCount = 2,\ + .bFunctionClass = CDC_CLASS_COMM,\ + .bFunctionSubClass = CDC_SUBCLASS_ACM,\ + .bFunctionProtocol = CDC_PROTOCOL_V25TER,\ + .bFirstInterface = UDI_CDC_COMM_IFACE_NUMBER_##port,\ + .iFunction = UDI_CDC_IAD_STRING_ID_##port,\ + } + +//! Content of CDC COMM interface descriptor for all speeds +#define UDI_CDC_COMM_DESC(port) { \ + .iface.bLength = sizeof(usb_iface_desc_t),\ + .iface.bDescriptorType = USB_DT_INTERFACE,\ + .iface.bAlternateSetting = 0,\ + .iface.bNumEndpoints = 1,\ + .iface.bInterfaceClass = CDC_CLASS_COMM,\ + .iface.bInterfaceSubClass = CDC_SUBCLASS_ACM,\ + .iface.bInterfaceProtocol = CDC_PROTOCOL_V25TER,\ + .header.bFunctionLength = sizeof(usb_cdc_hdr_desc_t),\ + .header.bDescriptorType = CDC_CS_INTERFACE,\ + .header.bDescriptorSubtype = CDC_SCS_HEADER,\ + .header.bcdCDC = LE16(0x0110),\ + .call_mgmt.bFunctionLength = sizeof(usb_cdc_call_mgmt_desc_t),\ + .call_mgmt.bDescriptorType = CDC_CS_INTERFACE,\ + .call_mgmt.bDescriptorSubtype = CDC_SCS_CALL_MGMT,\ + .call_mgmt.bmCapabilities = \ + CDC_CALL_MGMT_SUPPORTED | CDC_CALL_MGMT_OVER_DCI,\ + .acm.bFunctionLength = sizeof(usb_cdc_acm_desc_t),\ + .acm.bDescriptorType = CDC_CS_INTERFACE,\ + .acm.bDescriptorSubtype = CDC_SCS_ACM,\ + .acm.bmCapabilities = CDC_ACM_SUPPORT_LINE_REQUESTS,\ + .union_desc.bFunctionLength = sizeof(usb_cdc_union_desc_t),\ + .union_desc.bDescriptorType = CDC_CS_INTERFACE,\ + .union_desc.bDescriptorSubtype= CDC_SCS_UNION,\ + .ep_notify.bLength = sizeof(usb_ep_desc_t),\ + .ep_notify.bDescriptorType = USB_DT_ENDPOINT,\ + .ep_notify.bmAttributes = USB_EP_TYPE_INTERRUPT,\ + .ep_notify.wMaxPacketSize = LE16(UDI_CDC_COMM_EP_SIZE),\ + .ep_notify.bInterval = 0x10,\ + .ep_notify.bEndpointAddress = UDI_CDC_COMM_EP_##port,\ + .iface.bInterfaceNumber = UDI_CDC_COMM_IFACE_NUMBER_##port,\ + .call_mgmt.bDataInterface = UDI_CDC_DATA_IFACE_NUMBER_##port,\ + .union_desc.bMasterInterface = UDI_CDC_COMM_IFACE_NUMBER_##port,\ + .union_desc.bSlaveInterface0 = UDI_CDC_DATA_IFACE_NUMBER_##port,\ + .iface.iInterface = UDI_CDC_COMM_STRING_ID_##port,\ + } + +//! Content of CDC DATA interface descriptors +#define UDI_CDC_DATA_DESC_COMMON \ + .iface.bLength = sizeof(usb_iface_desc_t),\ + .iface.bDescriptorType = USB_DT_INTERFACE,\ + .iface.bAlternateSetting = 0,\ + .iface.bNumEndpoints = 2,\ + .iface.bInterfaceClass = CDC_CLASS_DATA,\ + .iface.bInterfaceSubClass = 0,\ + .iface.bInterfaceProtocol = 0,\ + .ep_in.bLength = sizeof(usb_ep_desc_t),\ + .ep_in.bDescriptorType = USB_DT_ENDPOINT,\ + .ep_in.bmAttributes = USB_EP_TYPE_BULK,\ + .ep_in.bInterval = 0,\ + .ep_out.bLength = sizeof(usb_ep_desc_t),\ + .ep_out.bDescriptorType = USB_DT_ENDPOINT,\ + .ep_out.bmAttributes = USB_EP_TYPE_BULK,\ + .ep_out.bInterval = 0, + +#define UDI_CDC_DATA_DESC_FS(port) { \ + UDI_CDC_DATA_DESC_COMMON \ + .ep_in.wMaxPacketSize = LE16(UDI_CDC_DATA_EPS_FS_SIZE),\ + .ep_out.wMaxPacketSize = LE16(UDI_CDC_DATA_EPS_FS_SIZE),\ + .ep_in.bEndpointAddress = UDI_CDC_DATA_EP_IN_##port,\ + .ep_out.bEndpointAddress = UDI_CDC_DATA_EP_OUT_##port,\ + .iface.bInterfaceNumber = UDI_CDC_DATA_IFACE_NUMBER_##port,\ + .iface.iInterface = UDI_CDC_DATA_STRING_ID_##port,\ + } + +#define UDI_CDC_DATA_DESC_HS(port) { \ + UDI_CDC_DATA_DESC_COMMON \ + .ep_in.wMaxPacketSize = LE16(UDI_CDC_DATA_EPS_HS_SIZE),\ + .ep_out.wMaxPacketSize = LE16(UDI_CDC_DATA_EPS_HS_SIZE),\ + .ep_in.bEndpointAddress = UDI_CDC_DATA_EP_IN_##port,\ + .ep_out.bEndpointAddress = UDI_CDC_DATA_EP_OUT_##port,\ + .iface.bInterfaceNumber = UDI_CDC_DATA_IFACE_NUMBER_##port,\ + .iface.iInterface = UDI_CDC_DATA_STRING_ID_##port,\ + } + +//@} + +/** + * \ingroup udi_group + * \defgroup udi_cdc_group USB Device Interface (UDI) for Communication Class Device (CDC) + * + * Common APIs used by high level application to use this USB class. + * + * These routines are used to transfer and control data + * to/from USB CDC endpoint. + * + * See \ref udi_cdc_quickstart. + * @{ + */ + +/** + * \name Interface for application with single CDC interface support + */ +//@{ + +/** + * \brief Notify a state change of DCD signal + * + * \param b_set DCD is enabled if true, else disabled + */ +void udi_cdc_ctrl_signal_dcd(bool b_set); + +/** + * \brief Notify a state change of DSR signal + * + * \param b_set DSR is enabled if true, else disabled + */ +void udi_cdc_ctrl_signal_dsr(bool b_set); + +/** + * \brief Notify a framing error + */ +void udi_cdc_signal_framing_error(void); + +/** + * \brief Notify a parity error + */ +void udi_cdc_signal_parity_error(void); + +/** + * \brief Notify a overrun + */ +void udi_cdc_signal_overrun(void); + +/** + * \brief This function checks if a character has been received on the CDC line + * + * \return \c 1 if a byte is ready to be read. + */ +bool udi_cdc_is_rx_ready(void); + +/** + * \brief Waits and gets a value on CDC line + * + * \return value read on CDC line + */ +int udi_cdc_getc(void); + +/** + * \brief Reads a RAM buffer on CDC line + * + * \param buf Values read + * \param size Number of value read + * + * \return the number of data remaining + */ +iram_size_t udi_cdc_read_buf(void* buf, iram_size_t size); + +/** + * \brief This function checks if a new character sent is possible + * The type int is used to support scanf redirection from compiler LIB. + * + * \return \c 1 if a new character can be sent + */ +bool udi_cdc_is_tx_ready(void); + +/** + * \brief Puts a byte on CDC line + * The type int is used to support printf redirection from compiler LIB. + * + * \param value Value to put + * + * \return \c 1 if function was successfully done, otherwise \c 0. + */ +int udi_cdc_putc(int value); + +/** + * \brief Writes a RAM buffer on CDC line + * + * \param buf Values to write + * \param size Number of value to write + * + * \return the number of data remaining + */ +iram_size_t udi_cdc_write_buf(const void* buf, iram_size_t size); +//@} + +/** + * \name Interface for application with multi CDC interfaces support + */ +//@{ + +/** + * \brief Notify a state change of DCD signal + * + * \param port Communication port number to manage + * \param b_set DCD is enabled if true, else disabled + */ +void udi_cdc_multi_ctrl_signal_dcd(uint8_t port, bool b_set); + +/** + * \brief Notify a state change of DSR signal + * + * \param port Communication port number to manage + * \param b_set DSR is enabled if true, else disabled + */ +void udi_cdc_multi_ctrl_signal_dsr(uint8_t port, bool b_set); + +/** + * \brief Notify a framing error + * + * \param port Communication port number to manage + */ +void udi_cdc_multi_signal_framing_error(uint8_t port); + +/** + * \brief Notify a parity error + * + * \param port Communication port number to manage + */ +void udi_cdc_multi_signal_parity_error(uint8_t port); + +/** + * \brief Notify a overrun + * + * \param port Communication port number to manage + */ +void udi_cdc_multi_signal_overrun(uint8_t port); + +/** + * \brief This function checks if a character has been received on the CDC line + * + * \param port Communication port number to manage + * + * \return \c 1 if a byte is ready to be read. + */ +bool udi_cdc_multi_is_rx_ready(uint8_t port); + +/** + * \brief Waits and gets a value on CDC line + * + * \param port Communication port number to manage + * + * \return value read on CDC line + */ +int udi_cdc_multi_getc(uint8_t port); + +/** + * \brief Reads a RAM buffer on CDC line + * + * \param port Communication port number to manage + * \param buf Values read + * \param size Number of values read + * + * \return the number of data remaining + */ +iram_size_t udi_cdc_multi_read_buf(uint8_t port, void* buf, iram_size_t size); + +/** + * \brief This function checks if a new character sent is possible + * The type int is used to support scanf redirection from compiler LIB. + * + * \param port Communication port number to manage + * + * \return \c 1 if a new character can be sent + */ +bool udi_cdc_multi_is_tx_ready(uint8_t port); + +/** + * \brief Puts a byte on CDC line + * The type int is used to support printf redirection from compiler LIB. + * + * \param port Communication port number to manage + * \param value Value to put + * + * \return \c 1 if function was successfully done, otherwise \c 0. + */ +int udi_cdc_multi_putc(uint8_t port, int value); + +/** + * \brief Writes a RAM buffer on CDC line + * + * \param port Communication port number to manage + * \param buf Values to write + * \param size Number of value to write + * + * \return the number of data remaining + */ +iram_size_t udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t size); +//@} + +//@} + +/** + * \page udi_cdc_quickstart Quick start guide for USB device Communication Class Device module (UDI CDC) + * + * This is the quick start guide for the \ref udi_cdc_group + * "USB device interface CDC module (UDI CDC)" with step-by-step instructions on + * how to configure and use the modules in a selection of use cases. + * + * The use cases contain several code fragments. The code fragments in the + * steps for setup can be copied into a custom initialization function, while + * the steps for usage can be copied into, e.g., the main application function. + * + * \section udi_cdc_basic_use_case Basic use case + * In this basic use case, the "USB CDC (Single Interface Device)" module is used + * with only one communication port. + * The "USB CDC (Composite Device)" module usage is described in \ref udi_cdc_use_cases + * "Advanced use cases". + * + * \section udi_cdc_basic_use_case_setup Setup steps + * \subsection udi_cdc_basic_use_case_setup_prereq Prerequisites + * \copydetails udc_basic_use_case_setup_prereq + * \subsection udi_cdc_basic_use_case_setup_code Example code + * \copydetails udc_basic_use_case_setup_code + * \subsection udi_cdc_basic_use_case_setup_flow Workflow + * \copydetails udc_basic_use_case_setup_flow + * + * \section udi_cdc_basic_use_case_usage Usage steps + * + * \subsection udi_cdc_basic_use_case_usage_code Example code + * Content of conf_usb.h: + * \code + * #define UDI_CDC_ENABLE_EXT(port) my_callback_cdc_enable() + * extern bool my_callback_cdc_enable(void); + * #define UDI_CDC_DISABLE_EXT(port) my_callback_cdc_disable() + * extern void my_callback_cdc_disable(void); + * #define UDI_CDC_LOW_RATE + * + * #define UDI_CDC_DEFAULT_RATE 115200 + * #define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 + * #define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE + * #define UDI_CDC_DEFAULT_DATABITS 8 + * + * #include "udi_cdc_conf.h" // At the end of conf_usb.h file + * \endcode + * + * Add to application C-file: + * \code + * static bool my_flag_autorize_cdc_transfert = false; + * bool my_callback_cdc_enable(void) + * { + * my_flag_autorize_cdc_transfert = true; + * return true; + * } + * void my_callback_cdc_disable(void) + * { + * my_flag_autorize_cdc_transfert = false; + * } + * + * void task(void) + * { + * if (my_flag_autorize_cdc_transfert) { + * udi_cdc_putc('A'); + * udi_cdc_getc(); + * } + * } + * \endcode + * + * \subsection udi_cdc_basic_use_case_setup_flow Workflow + * -# Ensure that conf_usb.h is available and contains the following configuration + * which is the USB device CDC configuration: + * - \code #define USB_DEVICE_SERIAL_NAME "12...EF" // Disk SN for CDC \endcode + * \note The USB serial number is mandatory when a CDC interface is used. + * - \code #define UDI_CDC_ENABLE_EXT(port) my_callback_cdc_enable() + * extern bool my_callback_cdc_enable(void); \endcode + * \note After the device enumeration (detecting and identifying USB devices), + * the USB host starts the device configuration. When the USB CDC interface + * from the device is accepted by the host, the USB host enables this interface and the + * UDI_CDC_ENABLE_EXT() callback function is called and return true. + * Thus, when this event is received, the data transfer on CDC interface are authorized. + * - \code #define UDI_CDC_DISABLE_EXT(port) my_callback_cdc_disable() + * extern void my_callback_cdc_disable(void); \endcode + * \note When the USB device is unplugged or is reset by the USB host, the USB + * interface is disabled and the UDI_CDC_DISABLE_EXT() callback function + * is called. Thus, the data transfer must be stopped on CDC interface. + * - \code #define UDI_CDC_LOW_RATE \endcode + * \note Define it when the transfer CDC Device to Host is a low rate + * (<512000 bauds) to reduce CDC buffers size. + * - \code #define UDI_CDC_DEFAULT_RATE 115200 + * #define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 + * #define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE + * #define UDI_CDC_DEFAULT_DATABITS 8 \endcode + * \note Default configuration of communication port at startup. + * -# Send or wait data on CDC line: + * - \code // Waits and gets a value on CDC line + * int udi_cdc_getc(void); + * // Reads a RAM buffer on CDC line + * iram_size_t udi_cdc_read_buf(int* buf, iram_size_t size); + * // Puts a byte on CDC line + * int udi_cdc_putc(int value); + * // Writes a RAM buffer on CDC line + * iram_size_t udi_cdc_write_buf(const int* buf, iram_size_t size); \endcode + * + * \section udi_cdc_use_cases Advanced use cases + * For more advanced use of the UDI CDC module, see the following use cases: + * - \subpage udi_cdc_use_case_composite + * - \subpage udc_use_case_1 + * - \subpage udc_use_case_2 + * - \subpage udc_use_case_3 + * - \subpage udc_use_case_4 + * - \subpage udc_use_case_5 + * - \subpage udc_use_case_6 + */ + +/** + * \page udi_cdc_use_case_composite CDC in a composite device + * + * A USB Composite Device is a USB Device which uses more than one USB class. + * In this use case, the "USB CDC (Composite Device)" module is used to + * create a USB composite device. Thus, this USB module can be associated with + * another "Composite Device" module, like "USB HID Mouse (Composite Device)". + * + * Also, you can refer to application note + * + * AVR4902 ASF - USB Composite Device. + * + * \section udi_cdc_use_case_composite_setup Setup steps + * For the setup code of this use case to work, the + * \ref udi_cdc_basic_use_case "basic use case" must be followed. + * + * \section udi_cdc_use_case_composite_usage Usage steps + * + * \subsection udi_cdc_use_case_composite_usage_code Example code + * Content of conf_usb.h: + * \code + * #define USB_DEVICE_EP_CTRL_SIZE 64 + * #define USB_DEVICE_NB_INTERFACE (X+2) + * #define USB_DEVICE_MAX_EP (X+3) + * + * #define UDI_CDC_DATA_EP_IN_0 (1 | USB_EP_DIR_IN) // TX + * #define UDI_CDC_DATA_EP_OUT_0 (2 | USB_EP_DIR_OUT) // RX + * #define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint + * #define UDI_CDC_COMM_IFACE_NUMBER_0 X+0 + * #define UDI_CDC_DATA_IFACE_NUMBER_0 X+1 + * + * #define UDI_COMPOSITE_DESC_T \ + * usb_iad_desc_t udi_cdc_iad; \ + * udi_cdc_comm_desc_t udi_cdc_comm; \ + * udi_cdc_data_desc_t udi_cdc_data; \ + * ... + * #define UDI_COMPOSITE_DESC_FS \ + * .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + * .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + * .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + * ... + * #define UDI_COMPOSITE_DESC_HS \ + * .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + * .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + * .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + * ... + * #define UDI_COMPOSITE_API \ + * &udi_api_cdc_comm, \ + * &udi_api_cdc_data, \ + * ... + * \endcode + * + * \subsection udi_cdc_use_case_composite_usage_flow Workflow + * -# Ensure that conf_usb.h is available and contains the following parameters + * required for a USB composite device configuration: + * - \code // Endpoint control size, This must be: + * // - 8, 16, 32 or 64 for full speed device (8 is recommended to save RAM) + * // - 64 for a high speed device + * #define USB_DEVICE_EP_CTRL_SIZE 64 + * // Total Number of interfaces on this USB device. + * // Add 2 for CDC. + * #define USB_DEVICE_NB_INTERFACE (X+2) + * // Total number of endpoints on this USB device. + * // This must include each endpoint for each interface. + * // Add 3 for CDC. + * #define USB_DEVICE_MAX_EP (X+3) \endcode + * -# Ensure that conf_usb.h contains the description of + * composite device: + * - \code // The endpoint numbers chosen by you for the CDC. + * // The endpoint numbers starting from 1. + * #define UDI_CDC_DATA_EP_IN_0 (1 | USB_EP_DIR_IN) // TX + * #define UDI_CDC_DATA_EP_OUT_0 (2 | USB_EP_DIR_OUT) // RX + * #define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint + * // The interface index of an interface starting from 0 + * #define UDI_CDC_COMM_IFACE_NUMBER_0 X+0 + * #define UDI_CDC_DATA_IFACE_NUMBER_0 X+1 \endcode + * -# Ensure that conf_usb.h contains the following parameters + * required for a USB composite device configuration: + * - \code // USB Interfaces descriptor structure + * #define UDI_COMPOSITE_DESC_T \ + * ... + * usb_iad_desc_t udi_cdc_iad; \ + * udi_cdc_comm_desc_t udi_cdc_comm; \ + * udi_cdc_data_desc_t udi_cdc_data; \ + * ... + * // USB Interfaces descriptor value for Full Speed + * #define UDI_COMPOSITE_DESC_FS \ + * ... + * .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + * .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + * .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + * ... + * // USB Interfaces descriptor value for High Speed + * #define UDI_COMPOSITE_DESC_HS \ + * ... + * .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + * .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + * .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + * ... + * // USB Interface APIs + * #define UDI_COMPOSITE_API \ + * ... + * &udi_api_cdc_comm, \ + * &udi_api_cdc_data, \ + * ... \endcode + * - \note The descriptors order given in the four lists above must be the + * same as the order defined by all interface indexes. The interface index + * orders are defined through UDI_X_IFACE_NUMBER defines.\n + * Also, the CDC requires a USB Interface Association Descriptor (IAD) for + * composite device. + */ + +#ifdef __cplusplus +} +#endif +#endif // _UDI_CDC_H_ diff --git a/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc_conf.h b/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc_conf.h new file mode 100644 index 0000000..69a5ff1 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc_conf.h @@ -0,0 +1,145 @@ +/** + * \file + * + * \brief Default CDC configuration for a USB Device with a single interface + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _UDI_CDC_CONF_H_ +#define _UDI_CDC_CONF_H_ + +#include "usb_protocol_cdc.h" +#include "conf_usb.h" + +#ifndef UDI_CDC_PORT_NB +# define UDI_CDC_PORT_NB 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup udi_cdc_group_single_desc + * @{ + */ + +//! Control endpoint size (Endpoint 0) +#define USB_DEVICE_EP_CTRL_SIZE 64 + +#if XMEGA +/** + * \name Endpoint configuration on XMEGA + * The XMEGA supports a IN and OUT endpoint with the same number endpoint, + * thus XMEGA can support up to 7 CDC interfaces. + */ +//@{ +#define UDI_CDC_DATA_EP_IN_0 ( 1 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 ( 2 | USB_EP_DIR_OUT) // RX +#define UDI_CDC_COMM_EP_0 ( 2 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_1 ( 3 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_1 ( 4 | USB_EP_DIR_OUT) // RX +#define UDI_CDC_COMM_EP_1 ( 4 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_2 ( 5 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_2 ( 6 | USB_EP_DIR_OUT) // RX +#define UDI_CDC_COMM_EP_2 ( 6 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_3 ( 7 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_3 ( 8 | USB_EP_DIR_OUT) // RX +#define UDI_CDC_COMM_EP_3 ( 8 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_4 ( 9 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_4 (10 | USB_EP_DIR_OUT) // RX +#define UDI_CDC_COMM_EP_4 (10 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_5 (11 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_5 (12 | USB_EP_DIR_OUT) // RX +#define UDI_CDC_COMM_EP_5 (12 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_6 (13 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_6 (14 | USB_EP_DIR_OUT) // RX +#define UDI_CDC_COMM_EP_6 (14 | USB_EP_DIR_IN) // Notify endpoint +//! 2 endpoints numbers used per CDC interface +#define USB_DEVICE_MAX_EP (2*UDI_CDC_PORT_NB) +//@} + +#else + +/** + * \name Default endpoint configuration + * The USBB, UDP, UDPHS and UOTGHS interfaces can support up to 2 CDC interfaces. + */ +//@{ +# if UDI_CDC_PORT_NB > 2 +# error USBB, UDP, UDPHS and UOTGHS interfaces have not enought endpoints. +# endif +#define UDI_CDC_DATA_EP_IN_0 (1 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (2 | USB_EP_DIR_OUT) // RX +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_1 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_1 (5 | USB_EP_DIR_OUT) // RX +#define UDI_CDC_COMM_EP_1 (6 | USB_EP_DIR_IN) // Notify endpoint +//! 3 endpoints used per CDC interface +#define USB_DEVICE_MAX_EP (3*UDI_CDC_PORT_NB) +//@} + +#endif + +/** + * \name Default Interface numbers + */ +//@{ +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 +#define UDI_CDC_COMM_IFACE_NUMBER_1 2 +#define UDI_CDC_DATA_IFACE_NUMBER_1 3 +#define UDI_CDC_COMM_IFACE_NUMBER_2 4 +#define UDI_CDC_DATA_IFACE_NUMBER_2 5 +#define UDI_CDC_COMM_IFACE_NUMBER_3 6 +#define UDI_CDC_DATA_IFACE_NUMBER_3 7 +#define UDI_CDC_COMM_IFACE_NUMBER_4 8 +#define UDI_CDC_DATA_IFACE_NUMBER_4 9 +#define UDI_CDC_COMM_IFACE_NUMBER_5 10 +#define UDI_CDC_DATA_IFACE_NUMBER_5 11 +#define UDI_CDC_COMM_IFACE_NUMBER_6 12 +#define UDI_CDC_DATA_IFACE_NUMBER_6 13 +//@} + +//@} + +#ifdef __cplusplus +} +#endif +#endif // _UDI_CDC_CONF_H_ diff --git a/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc_desc.c b/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc_desc.c new file mode 100644 index 0000000..e90e7b4 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/class/cdc/device/udi_cdc_desc.c @@ -0,0 +1,225 @@ +/** + * \file + * + * \brief Default descriptors for a USB Device with a single interface CDC + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#include "conf_usb.h" +#include "udd.h" +#include "udc_desc.h" +#include "udi_cdc.h" + + +/** + * \defgroup udi_cdc_group_single_desc USB device descriptors for a single interface + * + * The following structures provide the USB device descriptors required for + * USB Device with a single interface CDC. + * + * It is ready to use and do not require more definition. + * + * @{ + */ + +//! Two interfaces for a CDC device +#define USB_DEVICE_NB_INTERFACE (2*UDI_CDC_PORT_NB) + +//! USB Device Descriptor +COMPILER_WORD_ALIGNED +UDC_DESC_STORAGE usb_dev_desc_t udc_device_desc = { + .bLength = sizeof(usb_dev_desc_t), + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = LE16(USB_V2_0), +#if UDI_CDC_PORT_NB > 1 + .bDeviceClass = 0, +#else + .bDeviceClass = CDC_CLASS_DEVICE, +#endif + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = USB_DEVICE_EP_CTRL_SIZE, + .idVendor = LE16(USB_DEVICE_VENDOR_ID), + .idProduct = LE16(USB_DEVICE_PRODUCT_ID), + .bcdDevice = LE16((USB_DEVICE_MAJOR_VERSION << 8) + | USB_DEVICE_MINOR_VERSION), +#ifdef USB_DEVICE_MANUFACTURE_NAME + .iManufacturer = 1, +#else + .iManufacturer = 0, // No manufacture string +#endif +#ifdef USB_DEVICE_PRODUCT_NAME + .iProduct = 2, +#else + .iProduct = 0, // No product string +#endif +#ifdef USB_DEVICE_SERIAL_NAME + .iSerialNumber = 3, +#else + .iSerialNumber = 0, // No serial string +#endif + .bNumConfigurations = 1 +}; + + +#ifdef USB_DEVICE_HS_SUPPORT +//! USB Device Qualifier Descriptor for HS +COMPILER_WORD_ALIGNED +UDC_DESC_STORAGE usb_dev_qual_desc_t udc_device_qual = { + .bLength = sizeof(usb_dev_qual_desc_t), + .bDescriptorType = USB_DT_DEVICE_QUALIFIER, + .bcdUSB = LE16(USB_V2_0), +#if UDI_CDC_PORT_NB > 1 + .bDeviceClass = 0, +#else + .bDeviceClass = CDC_CLASS_DEVICE, +#endif + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = USB_DEVICE_EP_CTRL_SIZE, + .bNumConfigurations = 1 +}; +#endif + +//! Structure for USB Device Configuration Descriptor +COMPILER_PACK_SET(1) +typedef struct { + usb_conf_desc_t conf; +#if UDI_CDC_PORT_NB == 1 + udi_cdc_comm_desc_t udi_cdc_comm_0; + udi_cdc_data_desc_t udi_cdc_data_0; +#else +# define UDI_CDC_DESC_STRUCTURE(index, unused) \ + usb_iad_desc_t udi_cdc_iad_##index; \ + udi_cdc_comm_desc_t udi_cdc_comm_##index; \ + udi_cdc_data_desc_t udi_cdc_data_##index; + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_DESC_STRUCTURE, ~) +# undef UDI_CDC_DESC_STRUCTURE +#endif +} udc_desc_t; +COMPILER_PACK_RESET() + +//! USB Device Configuration Descriptor filled for full and high speed +COMPILER_WORD_ALIGNED +UDC_DESC_STORAGE udc_desc_t udc_desc_fs = { + .conf.bLength = sizeof(usb_conf_desc_t), + .conf.bDescriptorType = USB_DT_CONFIGURATION, + .conf.wTotalLength = LE16(sizeof(udc_desc_t)), + .conf.bNumInterfaces = USB_DEVICE_NB_INTERFACE, + .conf.bConfigurationValue = 1, + .conf.iConfiguration = 0, + .conf.bmAttributes = USB_CONFIG_ATTR_MUST_SET | USB_DEVICE_ATTR, + .conf.bMaxPower = USB_CONFIG_MAX_POWER(USB_DEVICE_POWER), +#if UDI_CDC_PORT_NB == 1 + .udi_cdc_comm_0 = UDI_CDC_COMM_DESC_0, + .udi_cdc_data_0 = UDI_CDC_DATA_DESC_0_FS, +#else +# define UDI_CDC_DESC_FS(index, unused) \ + .udi_cdc_iad_##index = UDI_CDC_IAD_DESC_##index,\ + .udi_cdc_comm_##index = UDI_CDC_COMM_DESC_##index,\ + .udi_cdc_data_##index = UDI_CDC_DATA_DESC_##index##_FS, + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_DESC_FS, ~) +# undef UDI_CDC_DESC_FS +#endif +}; + +#ifdef USB_DEVICE_HS_SUPPORT +COMPILER_WORD_ALIGNED +UDC_DESC_STORAGE udc_desc_t udc_desc_hs = { + .conf.bLength = sizeof(usb_conf_desc_t), + .conf.bDescriptorType = USB_DT_CONFIGURATION, + .conf.wTotalLength = LE16(sizeof(udc_desc_t)), + .conf.bNumInterfaces = USB_DEVICE_NB_INTERFACE, + .conf.bConfigurationValue = 1, + .conf.iConfiguration = 0, + .conf.bmAttributes = USB_CONFIG_ATTR_MUST_SET | USB_DEVICE_ATTR, + .conf.bMaxPower = USB_CONFIG_MAX_POWER(USB_DEVICE_POWER), +#if UDI_CDC_PORT_NB == 1 + .udi_cdc_comm_0 = UDI_CDC_COMM_DESC_0, + .udi_cdc_data_0 = UDI_CDC_DATA_DESC_0_HS, +#else +# define UDI_CDC_DESC_HS(index, unused) \ + .udi_cdc_iad_##index = UDI_CDC_IAD_DESC_##index, \ + .udi_cdc_comm_##index = UDI_CDC_COMM_DESC_##index, \ + .udi_cdc_data_##index = UDI_CDC_DATA_DESC_##index##_HS, + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_DESC_HS, ~) +# undef UDI_CDC_DESC_HS +#endif +}; +#endif + +/** + * \name UDC structures which content all USB Device definitions + */ +//@{ + +//! Associate an UDI for each USB interface +UDC_DESC_STORAGE udi_api_t *udi_apis[USB_DEVICE_NB_INTERFACE] = { +# define UDI_CDC_API(index, unused) \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, + MREPEAT(UDI_CDC_PORT_NB, UDI_CDC_API, ~) +# undef UDI_CDC_API +}; + +//! Add UDI with USB Descriptors FS & HS +UDC_DESC_STORAGE udc_config_speed_t udc_config_fs[1] = { { + .desc = (usb_conf_desc_t UDC_DESC_STORAGE*)&udc_desc_fs, + .udi_apis = udi_apis, +}}; +#ifdef USB_DEVICE_HS_SUPPORT +UDC_DESC_STORAGE udc_config_speed_t udc_config_hs[1] = { { + .desc = (usb_conf_desc_t UDC_DESC_STORAGE*)&udc_desc_hs, + .udi_apis = udi_apis, +}}; +#endif + +//! Add all information about USB Device in global structure for UDC +UDC_DESC_STORAGE udc_config_t udc_config = { + .confdev_lsfs = &udc_device_desc, + .conf_lsfs = udc_config_fs, +#ifdef USB_DEVICE_HS_SUPPORT + .confdev_hs = &udc_device_desc, + .qualifier = &udc_device_qual, + .conf_hs = udc_config_hs, +#endif +}; + +//@} +//@} diff --git a/DSTAT-temp/src/asf/common/services/usb/class/cdc/usb_protocol_cdc.h b/DSTAT-temp/src/asf/common/services/usb/class/cdc/usb_protocol_cdc.h new file mode 100644 index 0000000..ec6235a --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/class/cdc/usb_protocol_cdc.h @@ -0,0 +1,315 @@ +/** + * \file + * + * \brief USB Communication Device Class (CDC) protocol definitions + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef _USB_PROTOCOL_CDC_H_ +#define _USB_PROTOCOL_CDC_H_ + +#include "compiler.h" + +/** + * \ingroup usb_protocol_group + * \defgroup cdc_protocol_group Communication Device Class Definitions + * @{ + */ + +/** + * \name Possible values of class + */ +//@{ +#define CDC_CLASS_DEVICE 0x02 //!< USB Communication Device Class +#define CDC_CLASS_COMM 0x02 //!< CDC Communication Class Interface +#define CDC_CLASS_DATA 0x0A //!< CDC Data Class Interface +//@} + +//! \name USB CDC Subclass IDs +//@{ +#define CDC_SUBCLASS_DLCM 0x01 //!< Direct Line Control Model +#define CDC_SUBCLASS_ACM 0x02 //!< Abstract Control Model +#define CDC_SUBCLASS_TCM 0x03 //!< Telephone Control Model +#define CDC_SUBCLASS_MCCM 0x04 //!< Multi-Channel Control Model +#define CDC_SUBCLASS_CCM 0x05 //!< CAPI Control Model +#define CDC_SUBCLASS_ETH 0x06 //!< Ethernet Networking Control Model +#define CDC_SUBCLASS_ATM 0x07 //!< ATM Networking Control Model +//@} + +//! \name USB CDC Communication Interface Protocol IDs +//@{ +#define CDC_PROTOCOL_V25TER 0x01 //!< Common AT commands +//@} + +//! \name USB CDC Data Interface Protocol IDs +//@{ +#define CDC_PROTOCOL_I430 0x30 //!< ISDN BRI +#define CDC_PROTOCOL_HDLC 0x31 //!< HDLC +#define CDC_PROTOCOL_TRANS 0x32 //!< Transparent +#define CDC_PROTOCOL_Q921M 0x50 //!< Q.921 management protocol +#define CDC_PROTOCOL_Q921 0x51 //!< Q.931 [sic] Data link protocol +#define CDC_PROTOCOL_Q921TM 0x52 //!< Q.921 TEI-multiplexor +#define CDC_PROTOCOL_V42BIS 0x90 //!< Data compression procedures +#define CDC_PROTOCOL_Q931 0x91 //!< Euro-ISDN protocol control +#define CDC_PROTOCOL_V120 0x92 //!< V.24 rate adaption to ISDN +#define CDC_PROTOCOL_CAPI20 0x93 //!< CAPI Commands +#define CDC_PROTOCOL_HOST 0xFD //!< Host based driver +/** + * \brief Describes the Protocol Unit Functional Descriptors [sic] + * on Communication Class Interface + */ +#define CDC_PROTOCOL_PUFD 0xFE +//@} + +//! \name USB CDC Functional Descriptor Types +//@{ +#define CDC_CS_INTERFACE 0x24 //!< Interface Functional Descriptor +#define CDC_CS_ENDPOINT 0x25 //!< Endpoint Functional Descriptor +//@} + +//! \name USB CDC Functional Descriptor Subtypes +//@{ +#define CDC_SCS_HEADER 0x00 //!< Header Functional Descriptor +#define CDC_SCS_CALL_MGMT 0x01 //!< Call Management +#define CDC_SCS_ACM 0x02 //!< Abstract Control Management +#define CDC_SCS_UNION 0x06 //!< Union Functional Descriptor +//@} + +//! \name USB CDC Request IDs +//@{ +#define USB_REQ_CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define USB_REQ_CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define USB_REQ_CDC_SET_COMM_FEATURE 0x02 +#define USB_REQ_CDC_GET_COMM_FEATURE 0x03 +#define USB_REQ_CDC_CLEAR_COMM_FEATURE 0x04 +#define USB_REQ_CDC_SET_AUX_LINE_STATE 0x10 +#define USB_REQ_CDC_SET_HOOK_STATE 0x11 +#define USB_REQ_CDC_PULSE_SETUP 0x12 +#define USB_REQ_CDC_SEND_PULSE 0x13 +#define USB_REQ_CDC_SET_PULSE_TIME 0x14 +#define USB_REQ_CDC_RING_AUX_JACK 0x15 +#define USB_REQ_CDC_SET_LINE_CODING 0x20 +#define USB_REQ_CDC_GET_LINE_CODING 0x21 +#define USB_REQ_CDC_SET_CONTROL_LINE_STATE 0x22 +#define USB_REQ_CDC_SEND_BREAK 0x23 +#define USB_REQ_CDC_SET_RINGER_PARMS 0x30 +#define USB_REQ_CDC_GET_RINGER_PARMS 0x31 +#define USB_REQ_CDC_SET_OPERATION_PARMS 0x32 +#define USB_REQ_CDC_GET_OPERATION_PARMS 0x33 +#define USB_REQ_CDC_SET_LINE_PARMS 0x34 +#define USB_REQ_CDC_GET_LINE_PARMS 0x35 +#define USB_REQ_CDC_DIAL_DIGITS 0x36 +#define USB_REQ_CDC_SET_UNIT_PARAMETER 0x37 +#define USB_REQ_CDC_GET_UNIT_PARAMETER 0x38 +#define USB_REQ_CDC_CLEAR_UNIT_PARAMETER 0x39 +#define USB_REQ_CDC_GET_PROFILE 0x3A +#define USB_REQ_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define USB_REQ_CDC_SET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x41 +#define USB_REQ_CDC_GET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x42 +#define USB_REQ_CDC_SET_ETHERNET_PACKET_FILTER 0x43 +#define USB_REQ_CDC_GET_ETHERNET_STATISTIC 0x44 +#define USB_REQ_CDC_SET_ATM_DATA_FORMAT 0x50 +#define USB_REQ_CDC_GET_ATM_DEVICE_STATISTICS 0x51 +#define USB_REQ_CDC_SET_ATM_DEFAULT_VC 0x52 +#define USB_REQ_CDC_GET_ATM_VC_STATISTICS 0x53 +// Added bNotification codes according cdc spec 1.1 chapter 6.3 +#define USB_REQ_CDC_NOTIFY_RING_DETECT 0x09 +#define USB_REQ_CDC_NOTIFY_SERIAL_STATE 0x20 +#define USB_REQ_CDC_NOTIFY_CALL_STATE_CHANGE 0x28 +#define USB_REQ_CDC_NOTIFY_LINE_STATE_CHANGE 0x29 +//@} + +/* + * Need to pack structures tightly, or the compiler might insert padding + * and violate the spec-mandated layout. + */ +COMPILER_PACK_SET(1) + +//! \name USB CDC Descriptors +//@{ + + +//! CDC Header Functional Descriptor +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + le16_t bcdCDC; +} usb_cdc_hdr_desc_t; + +//! CDC Call Management Functional Descriptor +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; + uint8_t bDataInterface; +} usb_cdc_call_mgmt_desc_t; + +//! CDC ACM Functional Descriptor +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; +} usb_cdc_acm_desc_t; + +//! CDC Union Functional Descriptor +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bMasterInterface; + uint8_t bSlaveInterface0; +} usb_cdc_union_desc_t; + + +//! \name USB CDC Call Management Capabilities +//@{ +//! Device handles call management itself +#define CDC_CALL_MGMT_SUPPORTED (1 << 0) +//! Device can send/receive call management info over a Data Class interface +#define CDC_CALL_MGMT_OVER_DCI (1 << 1) +//@} + +//! \name USB CDC ACM Capabilities +//@{ +//! Device supports the request combination of +//! Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. +#define CDC_ACM_SUPPORT_FEATURE_REQUESTS (1 << 0) +//! Device supports the request combination of +//! Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, +//! and the notification Serial_State. +#define CDC_ACM_SUPPORT_LINE_REQUESTS (1 << 1) +//! Device supports the request Send_Break +#define CDC_ACM_SUPPORT_SENDBREAK_REQUESTS (1 << 2) +//! Device supports the notification Network_Connection. +#define CDC_ACM_SUPPORT_NOTIFY_REQUESTS (1 << 3) +//@} +//@} + +//! \name USB CDC line control +//@{ + +//! \name USB CDC line coding +//@{ +//! Line Coding structure +typedef struct { + le32_t dwDTERate; + uint8_t bCharFormat; + uint8_t bParityType; + uint8_t bDataBits; +} usb_cdc_line_coding_t; +//! Possible values of bCharFormat +enum cdc_char_format { + CDC_STOP_BITS_1 = 0, //!< 1 stop bit + CDC_STOP_BITS_1_5 = 1, //!< 1.5 stop bits + CDC_STOP_BITS_2 = 2, //!< 2 stop bits +}; +//! Possible values of bParityType +enum cdc_parity { + CDC_PAR_NONE = 0, //!< No parity + CDC_PAR_ODD = 1, //!< Odd parity + CDC_PAR_EVEN = 2, //!< Even parity + CDC_PAR_MARK = 3, //!< Parity forced to 0 (space) + CDC_PAR_SPACE = 4, //!< Parity forced to 1 (mark) +}; +//@} + +//! \name USB CDC control signals +//! spec 1.1 chapter 6.2.14 +//@{ + +//! Control signal structure +typedef struct { + uint16_t value; +} usb_cdc_control_signal_t; + +//! \name Possible values in usb_cdc_control_signal_t +//@{ +//! Carrier control for half duplex modems. +//! This signal corresponds to V.24 signal 105 and RS-232 signal RTS. +//! The device ignores the value of this bit +//! when operating in full duplex mode. +#define CDC_CTRL_SIGNAL_ACTIVATE_CARRIER (1 << 1) +//! Indicates to DCE if DTE is present or not. +//! This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR. +#define CDC_CTRL_SIGNAL_DTE_PRESENT (1 << 0) +//@} +//@} + + +//! \name USB CDC notification message +//@{ + +typedef struct { + uint8_t bmRequestType; + uint8_t bNotification; + le16_t wValue; + le16_t wIndex; + le16_t wLength; +} usb_cdc_notify_msg_t; + +//! \name USB CDC serial state +//@{* + +//! Hardware handshake support (cdc spec 1.1 chapter 6.3.5) +typedef struct { + usb_cdc_notify_msg_t header; + le16_t value; +} usb_cdc_notify_serial_state_t; + +//! \name Possible values in usb_cdc_notify_serial_state_t +//@{ +#define CDC_SERIAL_STATE_DCD CPU_TO_LE16((1<<0)) +#define CDC_SERIAL_STATE_DSR CPU_TO_LE16((1<<1)) +#define CDC_SERIAL_STATE_BREAK CPU_TO_LE16((1<<2)) +#define CDC_SERIAL_STATE_RING CPU_TO_LE16((1<<3)) +#define CDC_SERIAL_STATE_FRAMING CPU_TO_LE16((1<<4)) +#define CDC_SERIAL_STATE_PARITY CPU_TO_LE16((1<<5)) +#define CDC_SERIAL_STATE_OVERRUN CPU_TO_LE16((1<<6)) +//@} +//! @} + +//! @} + +COMPILER_PACK_RESET() + +//! @} + +#endif // _USB_PROTOCOL_CDC_H_ diff --git a/DSTAT-temp/src/asf/common/services/usb/udc/udc.c b/DSTAT-temp/src/asf/common/services/usb/udc/udc.c new file mode 100644 index 0000000..744ea1b --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/udc/udc.c @@ -0,0 +1,1090 @@ +/** + * \file + * + * \brief USB Device Controller (UDC) + * + * Copyright (c) 2009 - 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#include "conf_usb.h" +#include "usb_protocol.h" +#include "udd.h" +#include "udc_desc.h" +#include "udi.h" +#include "udc.h" + +/** + * \ingroup udc_group + * \defgroup udc_group_interne Implementation of UDC + * + * Internal implementation + * @{ + */ + +//! \name Internal variables to manage the USB device +//! @{ + +//! Device status state (see enum usb_device_status in usb_protocol.h) +static le16_t udc_device_status; + +//! Device Configuration number selected by the USB host +static uint8_t udc_num_configuration = 0; + +//! Pointer on the selected speed device configuration +static udc_config_speed_t UDC_DESC_STORAGE *udc_ptr_conf; + +//! Pointer on interface descriptor used by SETUP request. +static usb_iface_desc_t UDC_DESC_STORAGE *udc_ptr_iface; + +//! @} + + +//! \name Internal structure to store the USB device main strings +//! @{ + +/** + * \brief Language ID of USB device (US ID by default) + */ +COMPILER_WORD_ALIGNED +static UDC_DESC_STORAGE usb_str_lgid_desc_t udc_string_desc_languageid = { + .desc.bLength = sizeof(usb_str_lgid_desc_t), + .desc.bDescriptorType = USB_DT_STRING, + .string = {LE16(USB_LANGID_EN_US)} +}; + +/** + * \brief USB device manufacture name storage + * String is allocated only if USB_DEVICE_MANUFACTURE_NAME is declared + * by usb application configuration + */ +#ifdef USB_DEVICE_MANUFACTURE_NAME +static uint8_t udc_string_manufacturer_name[] = USB_DEVICE_MANUFACTURE_NAME; +# define USB_DEVICE_MANUFACTURE_NAME_SIZE \ + (sizeof(udc_string_manufacturer_name)-1) +#else +# define USB_DEVICE_MANUFACTURE_NAME_SIZE 0 +#endif + +/** + * \brief USB device product name storage + * String is allocated only if USB_DEVICE_PRODUCT_NAME is declared + * by usb application configuration + */ +#ifdef USB_DEVICE_PRODUCT_NAME +static uint8_t udc_string_product_name[] = USB_DEVICE_PRODUCT_NAME; +# define USB_DEVICE_PRODUCT_NAME_SIZE (sizeof(udc_string_product_name)-1) +#else +# define USB_DEVICE_PRODUCT_NAME_SIZE 0 +#endif + +/** + * \brief Get USB device serial number + * + * Use the define USB_DEVICE_SERIAL_NAME to set static serial number. + * + * For dynamic serial number set the define USB_DEVICE_GET_SERIAL_NAME_POINTER + * to a suitable pointer. This will also require the serial number length + * define USB_DEVICE_GET_SERIAL_NAME_LENGTH. + */ +#if defined USB_DEVICE_GET_SERIAL_NAME_POINTER + static const uint8_t *udc_get_string_serial_name(void) + { + return (const uint8_t *)USB_DEVICE_GET_SERIAL_NAME_POINTER; + } +# define USB_DEVICE_SERIAL_NAME_SIZE \ + USB_DEVICE_GET_SERIAL_NAME_LENGTH +#elif defined USB_DEVICE_SERIAL_NAME + static const uint8_t *udc_get_string_serial_name(void) + { + return (const uint8_t *)USB_DEVICE_SERIAL_NAME; + } +# define USB_DEVICE_SERIAL_NAME_SIZE \ + (sizeof(USB_DEVICE_SERIAL_NAME)-1) +#else +# define USB_DEVICE_SERIAL_NAME_SIZE 0 +#endif + +/** + * \brief USB device string descriptor + * Structure used to transfer ASCII strings to USB String descriptor structure. + */ +struct udc_string_desc_t { + usb_str_desc_t header; + le16_t string[Max(Max(USB_DEVICE_MANUFACTURE_NAME_SIZE, \ + USB_DEVICE_PRODUCT_NAME_SIZE), USB_DEVICE_SERIAL_NAME_SIZE)]; +}; +COMPILER_WORD_ALIGNED +static UDC_DESC_STORAGE struct udc_string_desc_t udc_string_desc = { + .header.bDescriptorType = USB_DT_STRING +}; +//! @} + +usb_iface_desc_t UDC_DESC_STORAGE *udc_get_interface_desc(void) +{ + return udc_ptr_iface; +} + +/** + * \brief Returns a value to check the end of USB Configuration descriptor + * + * \return address after the last byte of USB Configuration descriptor + */ +static usb_conf_desc_t UDC_DESC_STORAGE *udc_get_eof_conf(void) +{ + return (UDC_DESC_STORAGE usb_conf_desc_t *) ((uint8_t *) + udc_ptr_conf->desc + + le16_to_cpu(udc_ptr_conf->desc->wTotalLength)); +} + +#if (0!=USB_DEVICE_MAX_EP) +/** + * \brief Search specific descriptor in global interface descriptor + * + * \param desc Address of interface descriptor + * or previous specific descriptor found + * \param desc_id Descriptor ID to search + * + * \return address of specific descriptor found + * \return NULL if it is the end of global interface descriptor + */ +static usb_conf_desc_t UDC_DESC_STORAGE *udc_next_desc_in_iface(usb_conf_desc_t + UDC_DESC_STORAGE * desc, uint8_t desc_id) +{ + usb_conf_desc_t UDC_DESC_STORAGE *ptr_eof_desc; + + ptr_eof_desc = udc_get_eof_conf(); + // Go to next descriptor + desc = (UDC_DESC_STORAGE usb_conf_desc_t *) ((uint8_t *) desc + + desc->bLength); + // Check the end of configuration descriptor + while (ptr_eof_desc > desc) { + // If new interface descriptor is found, + // then it is the end of the current global interface descriptor + if (USB_DT_INTERFACE == desc->bDescriptorType) { + break; // End of global interface descriptor + } + if (desc_id == desc->bDescriptorType) { + return desc; // Specific descriptor found + } + // Go to next descriptor + desc = (UDC_DESC_STORAGE usb_conf_desc_t *) ((uint8_t *) desc + + desc->bLength); + } + return NULL; // No specific descriptor found +} +#endif + +/** + * \brief Search an interface descriptor + * This routine updates the internal pointer udc_ptr_iface. + * + * \param iface_num Interface number to find in Configuration Descriptor + * \param setting_num Setting number of interface to find + * + * \return 1 if found or 0 if not found + */ +static bool udc_update_iface_desc(uint8_t iface_num, uint8_t setting_num) +{ + usb_conf_desc_t UDC_DESC_STORAGE *ptr_end_desc; + + if (0 == udc_num_configuration) { + return false; + } + + if (iface_num >= udc_ptr_conf->desc->bNumInterfaces) { + return false; + } + + // Start at the beginning of configuration descriptor + udc_ptr_iface = (UDC_DESC_STORAGE usb_iface_desc_t *) + udc_ptr_conf->desc; + + // Check the end of configuration descriptor + ptr_end_desc = udc_get_eof_conf(); + while (ptr_end_desc > + (UDC_DESC_STORAGE usb_conf_desc_t *) udc_ptr_iface) { + if (USB_DT_INTERFACE == udc_ptr_iface->bDescriptorType) { + // A interface descriptor is found + // Check interface and alternate setting number + if ((iface_num == udc_ptr_iface->bInterfaceNumber) && + (setting_num == + udc_ptr_iface->bAlternateSetting)) { + return true; // Interface found + } + } + // Go to next descriptor + udc_ptr_iface = (UDC_DESC_STORAGE usb_iface_desc_t *) ( + (uint8_t *) udc_ptr_iface + + udc_ptr_iface->bLength); + } + return false; // Interface not found +} + +/** + * \brief Disables an usb device interface (UDI) + * This routine call the UDI corresponding to interface number + * + * \param iface_num Interface number to disable + * + * \return 1 if it is done or 0 if interface is not found + */ +static bool udc_iface_disable(uint8_t iface_num) +{ + udi_api_t UDC_DESC_STORAGE *udi_api; + + // Select first alternate setting of the interface + // to update udc_ptr_iface before call iface->getsetting() + if (!udc_update_iface_desc(iface_num, 0)) { + return false; + } + + // Select the interface with the current alternate setting + udi_api = udc_ptr_conf->udi_apis[iface_num]; + +#if (0!=USB_DEVICE_MAX_EP) + if (!udc_update_iface_desc(iface_num, udi_api->getsetting())) { + return false; + } + + // Start at the beginning of interface descriptor + { + usb_ep_desc_t UDC_DESC_STORAGE *ep_desc; + ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *) udc_ptr_iface; + while (1) { + // Search Endpoint descriptor included in global interface descriptor + ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *) + udc_next_desc_in_iface((UDC_DESC_STORAGE + usb_conf_desc_t *) + ep_desc, USB_DT_ENDPOINT); + if (NULL == ep_desc) { + break; + } + // Free the endpoint used by the interface + udd_ep_free(ep_desc->bEndpointAddress); + } + } +#endif + + // Disable interface + udi_api->disable(); + return true; +} + +/** + * \brief Enables an usb device interface (UDI) + * This routine calls the UDI corresponding + * to the interface and setting number. + * + * \param iface_num Interface number to enable + * \param setting_num Setting number to enable + * + * \return 1 if it is done or 0 if interface is not found + */ +static bool udc_iface_enable(uint8_t iface_num, uint8_t setting_num) +{ + // Select the interface descriptor + if (!udc_update_iface_desc(iface_num, setting_num)) { + return false; + } + +#if (0!=USB_DEVICE_MAX_EP) + usb_ep_desc_t UDC_DESC_STORAGE *ep_desc; + + // Start at the beginning of the global interface descriptor + ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *) udc_ptr_iface; + while (1) { + // Search Endpoint descriptor included in the global interface descriptor + ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *) + udc_next_desc_in_iface((UDC_DESC_STORAGE + usb_conf_desc_t *) ep_desc, + USB_DT_ENDPOINT); + if (NULL == ep_desc) + break; + // Alloc the endpoint used by the interface + if (!udd_ep_alloc(ep_desc->bEndpointAddress, + ep_desc->bmAttributes, + le16_to_cpu + (ep_desc->wMaxPacketSize))) { + return false; + } + } +#endif + // Enable the interface + return udc_ptr_conf->udi_apis[iface_num]->enable(); +} + +/*! \brief Start the USB Device stack + */ +void udc_start(void) +{ + udd_enable(); +} + +/*! \brief Stop the USB Device stack + */ +void udc_stop(void) +{ + udd_disable(); +} + +/** + * \brief Reset the current configuration of the USB device, + * This routines can be called by UDD when a RESET on the USB line occurs. + */ +void udc_reset(void) +{ + uint8_t iface_num; + + if (udc_num_configuration) { + for (iface_num = 0; + iface_num < udc_ptr_conf->desc->bNumInterfaces; + iface_num++) { + udc_iface_disable(iface_num); + } + } + udc_num_configuration = 0; +#if (USB_CONFIG_ATTR_REMOTE_WAKEUP \ + == (USB_DEVICE_ATTR & USB_CONFIG_ATTR_REMOTE_WAKEUP)) + if (CPU_TO_LE16(USB_DEV_STATUS_REMOTEWAKEUP) & udc_device_status) { + // Remote wakeup is enabled then disable it + UDC_REMOTEWAKEUP_DISABLE(); + } +#endif + udc_device_status = +#if (USB_DEVICE_ATTR & USB_CONFIG_ATTR_SELF_POWERED) + CPU_TO_LE16(USB_DEV_STATUS_SELF_POWERED); +#else + CPU_TO_LE16(USB_DEV_STATUS_BUS_POWERED); +#endif +} + +void udc_sof_notify(void) +{ + uint8_t iface_num; + + if (udc_num_configuration) { + for (iface_num = 0; + iface_num < udc_ptr_conf->desc->bNumInterfaces; + iface_num++) { + if (udc_ptr_conf->udi_apis[iface_num]->sof_notify != NULL) { + udc_ptr_conf->udi_apis[iface_num]->sof_notify(); + } + } + } +} + +/** + * \brief Standard device request to get device status + * + * \return true if success + */ +static bool udc_req_std_dev_get_status(void) +{ + if (udd_g_ctrlreq.req.wLength != sizeof(udc_device_status)) { + return false; + } + + udd_set_setup_payload( (uint8_t *) & udc_device_status, + sizeof(udc_device_status)); + return true; +} + +#if (0!=USB_DEVICE_MAX_EP) +/** + * \brief Standard endpoint request to get endpoint status + * + * \return true if success + */ +static bool udc_req_std_ep_get_status(void) +{ + static le16_t udc_ep_status; + + if (udd_g_ctrlreq.req.wLength != sizeof(udc_ep_status)) { + return false; + } + + udc_ep_status = udd_ep_is_halted(udd_g_ctrlreq.req. + wIndex & 0xFF) ? CPU_TO_LE16(USB_EP_STATUS_HALTED) : 0; + + udd_set_setup_payload( (uint8_t *) & udc_ep_status, + sizeof(udc_ep_status)); + return true; +} +#endif + +/** + * \brief Standard device request to change device status + * + * \return true if success + */ +static bool udc_req_std_dev_clear_feature(void) +{ + if (udd_g_ctrlreq.req.wLength) { + return false; + } + + if (udd_g_ctrlreq.req.wValue == USB_DEV_FEATURE_REMOTE_WAKEUP) { + udc_device_status &= CPU_TO_LE16(~(uint32_t)USB_DEV_STATUS_REMOTEWAKEUP); +#if (USB_CONFIG_ATTR_REMOTE_WAKEUP \ + == (USB_DEVICE_ATTR & USB_CONFIG_ATTR_REMOTE_WAKEUP)) + UDC_REMOTEWAKEUP_DISABLE(); +#endif + return true; + } + return false; +} + +#if (0!=USB_DEVICE_MAX_EP) +/** + * \brief Standard endpoint request to clear endpoint feature + * + * \return true if success + */ +static bool udc_req_std_ep_clear_feature(void) +{ + if (udd_g_ctrlreq.req.wLength) { + return false; + } + + if (udd_g_ctrlreq.req.wValue == USB_EP_FEATURE_HALT) { + return udd_ep_clear_halt(udd_g_ctrlreq.req.wIndex & 0xFF); + } + return false; +} +#endif + +/** + * \brief Standard device request to set a feature + * + * \return true if success + */ +static bool udc_req_std_dev_set_feature(void) +{ + if (udd_g_ctrlreq.req.wLength) { + return false; + } + + switch (udd_g_ctrlreq.req.wValue) { + + case USB_DEV_FEATURE_REMOTE_WAKEUP: +#if (USB_CONFIG_ATTR_REMOTE_WAKEUP \ + == (USB_DEVICE_ATTR & USB_CONFIG_ATTR_REMOTE_WAKEUP)) + udc_device_status |= CPU_TO_LE16(USB_DEV_STATUS_REMOTEWAKEUP); + UDC_REMOTEWAKEUP_ENABLE(); + return true; +#else + return false; +#endif + +#ifdef USB_DEVICE_HS_SUPPORT + case USB_DEV_FEATURE_TEST_MODE: + if (!udd_is_high_speed()) { + break; + } + if (udd_g_ctrlreq.req.wIndex & 0xff) { + break; + } + // Unconfigure the device, terminating all ongoing requests + udc_reset(); + switch ((udd_g_ctrlreq.req.wIndex >> 8) & 0xFF) { + case USB_DEV_TEST_MODE_J: + udd_g_ctrlreq.callback = udd_test_mode_j; + return true; + + case USB_DEV_TEST_MODE_K: + udd_g_ctrlreq.callback = udd_test_mode_k; + return true; + + case USB_DEV_TEST_MODE_SE0_NAK: + udd_g_ctrlreq.callback = udd_test_mode_se0_nak; + return true; + + case USB_DEV_TEST_MODE_PACKET: + udd_g_ctrlreq.callback = udd_test_mode_packet; + return true; + + case USB_DEV_TEST_MODE_FORCE_ENABLE: // Only for downstream facing hub ports + default: + break; + } + break; +#endif + default: + break; + } + return false; +} + +/** + * \brief Standard endpoint request to halt an endpoint + * + * \return true if success + */ +#if (0!=USB_DEVICE_MAX_EP) +static bool udc_req_std_ep_set_feature(void) +{ + if (udd_g_ctrlreq.req.wLength) { + return false; + } + if (udd_g_ctrlreq.req.wValue == USB_EP_FEATURE_HALT) { + udd_ep_abort(udd_g_ctrlreq.req.wIndex & 0xFF); + return udd_ep_set_halt(udd_g_ctrlreq.req.wIndex & 0xFF); + } + return false; +} +#endif + +/** + * \brief Change the address of device + * Callback called at the end of request set address + */ +static void udc_valid_address(void) +{ + udd_set_address(udd_g_ctrlreq.req.wValue & 0x7F); +} + +/** + * \brief Standard device request to set device address + * + * \return true if success + */ +static bool udc_req_std_dev_set_address(void) +{ + if (udd_g_ctrlreq.req.wLength) { + return false; + } + + // The address must be changed at the end of setup request after the handshake + // then we use a callback to change address + udd_g_ctrlreq.callback = udc_valid_address; + return true; +} + +/** + * \brief Standard device request to get device string descriptor + * + * \return true if success + */ +static bool udc_req_std_dev_get_str_desc(void) +{ + uint8_t i; + const uint8_t *str; + uint8_t str_length = 0; + + // Link payload pointer to the string corresponding at request + switch (udd_g_ctrlreq.req.wValue & 0xff) { + case 0: + udd_set_setup_payload((uint8_t *) &udc_string_desc_languageid, + sizeof(udc_string_desc_languageid)); + break; + +#ifdef USB_DEVICE_MANUFACTURE_NAME + case 1: + str_length = USB_DEVICE_MANUFACTURE_NAME_SIZE; + str = udc_string_manufacturer_name; + break; +#endif +#ifdef USB_DEVICE_PRODUCT_NAME + case 2: + str_length = USB_DEVICE_PRODUCT_NAME_SIZE; + str = udc_string_product_name; + break; +#endif +#if defined USB_DEVICE_SERIAL_NAME || defined USB_DEVICE_GET_SERIAL_NAME_POINTER + case 3: + str_length = USB_DEVICE_SERIAL_NAME_SIZE; + str = udc_get_string_serial_name(); + break; +#endif + default: +#ifdef UDC_GET_EXTRA_STRING + if (UDC_GET_EXTRA_STRING()) { + break; + } +#endif + return false; + } + + if (str_length) { + for(i = 0; i < str_length; i++) { + udc_string_desc.string[i] = cpu_to_le16((le16_t)str[i]); + } + + udc_string_desc.header.bLength = 2 + (str_length) * 2; + udd_set_setup_payload( + (uint8_t *) &udc_string_desc, + udc_string_desc.header.bLength); + } + + return true; +} + +/** + * \brief Standard device request to get descriptors about USB device + * + * \return true if success + */ +static bool udc_req_std_dev_get_descriptor(void) +{ + uint8_t conf_num; + + conf_num = udd_g_ctrlreq.req.wValue & 0xff; + + // Check descriptor ID + switch ((uint8_t) (udd_g_ctrlreq.req.wValue >> 8)) { + case USB_DT_DEVICE: + // Device descriptor requested +#ifdef USB_DEVICE_HS_SUPPORT + if (!udd_is_high_speed()) { + udd_set_setup_payload( + (uint8_t *) udc_config.confdev_hs, + udc_config.confdev_hs->bLength); + } else +#endif + { + udd_set_setup_payload( + (uint8_t *) udc_config.confdev_lsfs, + udc_config.confdev_lsfs->bLength); + } + break; + + case USB_DT_CONFIGURATION: + // Configuration descriptor requested +#ifdef USB_DEVICE_HS_SUPPORT + if (udd_is_high_speed()) { + // HS descriptor + if (conf_num >= udc_config.confdev_hs-> + bNumConfigurations) { + return false; + } + udd_set_setup_payload( + (uint8_t *)udc_config.conf_hs[conf_num].desc, + le16_to_cpu(udc_config.conf_hs[conf_num].desc->wTotalLength)); + } else +#endif + { + // FS descriptor + if (conf_num >= udc_config.confdev_lsfs-> + bNumConfigurations) { + return false; + } + udd_set_setup_payload( + (uint8_t *)udc_config.conf_lsfs[conf_num].desc, + le16_to_cpu(udc_config.conf_lsfs[conf_num].desc->wTotalLength)); + } + ((usb_conf_desc_t *) udd_g_ctrlreq.payload)->bDescriptorType = + USB_DT_CONFIGURATION; + break; + +#ifdef USB_DEVICE_HS_SUPPORT + case USB_DT_DEVICE_QUALIFIER: + // Device qualifier descriptor requested + udd_set_setup_payload( (uint8_t *) udc_config.qualifier, + udc_config.qualifier->bLength); + break; + + case USB_DT_OTHER_SPEED_CONFIGURATION: + // Other configuration descriptor requested + if (!udd_is_high_speed()) { + // HS descriptor + if (conf_num >= udc_config.confdev_hs-> + bNumConfigurations) { + return false; + } + udd_set_setup_payload( + (uint8_t *)udc_config.conf_hs[conf_num].desc, + le16_to_cpu(udc_config.conf_hs[conf_num].desc->wTotalLength)); + } else { + // FS descriptor + if (conf_num >= udc_config.confdev_lsfs-> + bNumConfigurations) { + return false; + } + udd_set_setup_payload( + (uint8_t *)udc_config.conf_lsfs[conf_num].desc, + le16_to_cpu(udc_config.conf_lsfs[conf_num].desc->wTotalLength)); + } + ((usb_conf_desc_t *) udd_g_ctrlreq.payload)->bDescriptorType = + USB_DT_OTHER_SPEED_CONFIGURATION; + break; +#endif + + case USB_DT_STRING: + // String descriptor requested + if (!udc_req_std_dev_get_str_desc()) { + return false; + } + break; + + default: + // Unknown descriptor requested + return false; + } + // if the descriptor is larger than length requested, then reduce it + if (udd_g_ctrlreq.req.wLength < udd_g_ctrlreq.payload_size) { + udd_g_ctrlreq.payload_size = udd_g_ctrlreq.req.wLength; + } + return true; +} + +/** + * \brief Standard device request to get configuration number + * + * \return true if success + */ +static bool udc_req_std_dev_get_configuration(void) +{ + if (udd_g_ctrlreq.req.wLength != 1) { + return false; + } + + udd_set_setup_payload(&udc_num_configuration,1); + return true; +} + +/** + * \brief Standard device request to enable a configuration + * + * \return true if success + */ +static bool udc_req_std_dev_set_configuration(void) +{ + uint8_t iface_num; + + // Check request length + if (udd_g_ctrlreq.req.wLength) { + return false; + } + // Authorize configuration only if the address is valid + if (!udd_getaddress()) { + return false; + } + // Check the configuration number requested +#ifdef USB_DEVICE_HS_SUPPORT + if (udd_is_high_speed()) { + // HS descriptor + if ((udd_g_ctrlreq.req.wValue & 0xFF) > + udc_config.confdev_hs->bNumConfigurations) { + return false; + } + } else +#endif + { + // FS descriptor + if ((udd_g_ctrlreq.req.wValue & 0xFF) > + udc_config.confdev_lsfs->bNumConfigurations) { + return false; + } + } + + // Reset current configuration + udc_reset(); + + // Enable new configuration + udc_num_configuration = udd_g_ctrlreq.req.wValue & 0xFF; + if (udc_num_configuration == 0) { + return true; // Default empty configuration requested + } + // Update pointer of the configuration descriptor +#ifdef USB_DEVICE_HS_SUPPORT + if (udd_is_high_speed()) { + // HS descriptor + udc_ptr_conf = &udc_config.conf_hs[udc_num_configuration - 1]; + } else +#endif + { + // FS descriptor + udc_ptr_conf = &udc_config.conf_lsfs[udc_num_configuration - 1]; + } + // Enable all interfaces of the selected configuration + for (iface_num = 0; iface_num < udc_ptr_conf->desc->bNumInterfaces; + iface_num++) { + if (!udc_iface_enable(iface_num, 0)) { + return false; + } + } + return true; +} + +/** + * \brief Standard interface request + * to get the alternate setting number of an interface + * + * \return true if success + */ +static bool udc_req_std_iface_get_setting(void) +{ + static uint8_t udc_iface_setting; + uint8_t iface_num; + udi_api_t UDC_DESC_STORAGE *udi_api; + + if (udd_g_ctrlreq.req.wLength != 1) { + return false; // Error in request + } + if (!udc_num_configuration) { + return false; // The device is not is configured state yet + } + + // Check the interface number included in the request + iface_num = udd_g_ctrlreq.req.wIndex & 0xFF; + if (iface_num >= udc_ptr_conf->desc->bNumInterfaces) { + return false; + } + + // Select first alternate setting of the interface to update udc_ptr_iface + // before call iface->getsetting() + if (!udc_update_iface_desc(iface_num, 0)) { + return false; + } + // Get alternate setting from UDI + udi_api = udc_ptr_conf->udi_apis[iface_num]; + udc_iface_setting = udi_api->getsetting(); + + // Link value to payload pointer of request + udd_set_setup_payload(&udc_iface_setting,1); + return true; +} + +/** + * \brief Standard interface request + * to set an alternate setting of an interface + * + * \return true if success + */ +static bool udc_req_std_iface_set_setting(void) +{ + uint8_t iface_num, setting_num; + + if (udd_g_ctrlreq.req.wLength) { + return false; // Error in request + } + if (!udc_num_configuration) { + return false; // The device is not is configured state yet + } + + iface_num = udd_g_ctrlreq.req.wIndex & 0xFF; + setting_num = udd_g_ctrlreq.req.wValue & 0xFF; + + // Disable current setting + if (!udc_iface_disable(iface_num)) { + return false; + } + + // Enable new setting + return udc_iface_enable(iface_num, setting_num); +} + +/** + * \brief Main routine to manage the standard USB SETUP request + * + * \return true if the request is supported + */ +static bool udc_reqstd(void) +{ + if (Udd_setup_is_in()) { + // GET Standard Requests + if (udd_g_ctrlreq.req.wLength == 0) { + return false; // Error for USB host + } + + if (USB_REQ_RECIP_DEVICE == Udd_setup_recipient()) { + // Standard Get Device request + switch (udd_g_ctrlreq.req.bRequest) { + case USB_REQ_GET_STATUS: + return udc_req_std_dev_get_status(); + case USB_REQ_GET_DESCRIPTOR: + return udc_req_std_dev_get_descriptor(); + case USB_REQ_GET_CONFIGURATION: + return udc_req_std_dev_get_configuration(); + default: + break; + } + } + + if (USB_REQ_RECIP_INTERFACE == Udd_setup_recipient()) { + // Standard Get Interface request + switch (udd_g_ctrlreq.req.bRequest) { + case USB_REQ_GET_INTERFACE: + return udc_req_std_iface_get_setting(); + default: + break; + } + } +#if (0!=USB_DEVICE_MAX_EP) + if (USB_REQ_RECIP_ENDPOINT == Udd_setup_recipient()) { + // Standard Get Endpoint request + switch (udd_g_ctrlreq.req.bRequest) { + case USB_REQ_GET_STATUS: + return udc_req_std_ep_get_status(); + default: + break; + } + } +#endif + } else { + // SET Standard Requests + if (USB_REQ_RECIP_DEVICE == Udd_setup_recipient()) { + // Standard Set Device request + switch (udd_g_ctrlreq.req.bRequest) { + case USB_REQ_SET_ADDRESS: + return udc_req_std_dev_set_address(); + case USB_REQ_CLEAR_FEATURE: + return udc_req_std_dev_clear_feature(); + case USB_REQ_SET_FEATURE: + return udc_req_std_dev_set_feature(); + case USB_REQ_SET_CONFIGURATION: + return udc_req_std_dev_set_configuration(); + case USB_REQ_SET_DESCRIPTOR: + /* Not supported (defined as optional by the USB 2.0 spec) */ + break; + default: + break; + } + } + + if (USB_REQ_RECIP_INTERFACE == Udd_setup_recipient()) { + // Standard Set Interface request + switch (udd_g_ctrlreq.req.bRequest) { + case USB_REQ_SET_INTERFACE: + return udc_req_std_iface_set_setting(); + default: + break; + } + } +#if (0!=USB_DEVICE_MAX_EP) + if (USB_REQ_RECIP_ENDPOINT == Udd_setup_recipient()) { + // Standard Set Endpoint request + switch (udd_g_ctrlreq.req.bRequest) { + case USB_REQ_CLEAR_FEATURE: + return udc_req_std_ep_clear_feature(); + case USB_REQ_SET_FEATURE: + return udc_req_std_ep_set_feature(); + default: + break; + } + } +#endif + } + return false; +} + +/** + * \brief Send the SETUP interface request to UDI + * + * \return true if the request is supported + */ +static bool udc_req_iface(void) +{ + uint8_t iface_num; + udi_api_t UDC_DESC_STORAGE *udi_api; + + if (0 == udc_num_configuration) { + return false; // The device is not is configured state yet + } + // Check interface number + iface_num = udd_g_ctrlreq.req.wIndex & 0xFF; + if (iface_num >= udc_ptr_conf->desc->bNumInterfaces) { + return false; + } + + //* To update udc_ptr_iface with the selected interface in request + // Select first alternate setting of interface to update udc_ptr_iface + // before calling udi_api->getsetting() + if (!udc_update_iface_desc(iface_num, 0)) { + return false; + } + // Select the interface with the current alternate setting + udi_api = udc_ptr_conf->udi_apis[iface_num]; + if (!udc_update_iface_desc(iface_num, udi_api->getsetting())) { + return false; + } + + // Send the SETUP request to the UDI corresponding to the interface number + return udi_api->setup(); +} + +/** + * \brief Main routine to manage the USB SETUP request. + * + * This function parses a USB SETUP request and submits an appropriate + * response back to the host or, in the case of SETUP OUT requests + * with data, sets up a buffer for receiving the data payload. + * + * The main standard requests defined by the USB 2.0 standard are handled + * internally. The interface requests are sent to UDI, and the specific request + * sent to a specific application callback. + * + * \return true if the request is supported, else the request is stalled by UDD + */ +bool udc_process_setup(void) +{ + // By default no data (receive/send) and no callbacks registered + udd_g_ctrlreq.payload_size = 0; + udd_g_ctrlreq.callback = NULL; + udd_g_ctrlreq.over_under_run = NULL; + + if (Udd_setup_is_in()) { + if (udd_g_ctrlreq.req.wLength == 0) { + return false; // Error from USB host + } + } + + // If standard request then try to decode it in UDC + if (Udd_setup_type() == USB_REQ_TYPE_STANDARD) { + if (udc_reqstd()) { + return true; + } + } + + // If interface request then try to decode it in UDI + if (Udd_setup_recipient() == USB_REQ_RECIP_INTERFACE) { + if (udc_req_iface()) { + return true; + } + } + + // Here SETUP request unknown by UDC and UDIs +#ifdef USB_DEVICE_SPECIFIC_REQUEST + // Try to decode it in specific callback + return USB_DEVICE_SPECIFIC_REQUEST(); // Ex: Vendor request,... +#else + return false; +#endif +} + +//! @} diff --git a/DSTAT-temp/src/asf/common/services/usb/udc/udc.h b/DSTAT-temp/src/asf/common/services/usb/udc/udc.h new file mode 100644 index 0000000..2929422 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/udc/udc.h @@ -0,0 +1,726 @@ +/** + * \file + * + * \brief Interface of the USB Device Controller (UDC) + * + * Copyright (c) 2009 - 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _UDC_H_ +#define _UDC_H_ + +#include "conf_usb.h" +#include "usb_protocol.h" +#include "udc_desc.h" +#include "udd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \ingroup usb_device_group + * \defgroup udc_group USB Device Controller (UDC) + * + * The UDC provides a high-level abstraction of the usb device. + * You can use these functions to control the main device state + * (start/attach/wakeup). + * + * \section USB_DEVICE_CONF USB Device Custom configuration + * The following USB Device configuration must be included in the conf_usb.h + * file of the application. + * + * USB_DEVICE_VENDOR_ID (Word)
+ * Vendor ID provided by USB org (ATMEL 0x03EB). + * + * USB_DEVICE_PRODUCT_ID (Word)
+ * Product ID (Referenced in usb_atmel.h). + * + * USB_DEVICE_MAJOR_VERSION (Byte)
+ * Major version of the device + * + * USB_DEVICE_MINOR_VERSION (Byte)
+ * Minor version of the device + * + * USB_DEVICE_MANUFACTURE_NAME (string)
+ * ASCII name for the manufacture + * + * USB_DEVICE_PRODUCT_NAME (string)
+ * ASCII name for the product + * + * USB_DEVICE_SERIAL_NAME (string)
+ * ASCII name to enable and set a serial number + * + * USB_DEVICE_POWER (Numeric)
+ * (unit mA) Maximum device power + * + * USB_DEVICE_ATTR (Byte)
+ * USB attributes available: + * - USB_CONFIG_ATTR_SELF_POWERED + * - USB_CONFIG_ATTR_REMOTE_WAKEUP + * Note: if remote wake enabled then defines remotewakeup callbacks, + * see Table 5-2. External API from UDC - Callback + * + * USB_DEVICE_LOW_SPEED (Only defined)
+ * Force the USB Device to run in low speed + * + * USB_DEVICE_HS_SUPPORT (Only defined)
+ * Authorize the USB Device to run in high speed + * + * USB_DEVICE_MAX_EP (Byte)
+ * Define the maximum endpoint number used by the USB Device.
+ * This one is already defined in UDI default configuration. + * Ex: + * - When endpoint control 0x00, endpoint 0x01 and + * endpoint 0x82 is used then USB_DEVICE_MAX_EP=2 + * - When only endpoint control 0x00 is used then USB_DEVICE_MAX_EP=0 + * - When endpoint 0x01 and endpoint 0x81 is used then USB_DEVICE_MAX_EP=1
+ * (configuration not possible on USBB interface) + * @{ + */ + +/** + * \brief Authorizes the VBUS event + * + * \return true, if the VBUS monitoring is possible. + * + * \section udc_vbus_monitoring VBus monitoring used cases + * + * The VBus monitoring is used only for USB SELF Power application. + * + * - No custom implementation \n + * // Authorize VBUS monitoring \n + * if (!udc_include_vbus_monitoring()) { \n + * // VBUS monitoring is not available on this product \n + * // thereby VBUS has to be considered as present \n + * // Attach USB Device \n + * udc_attach(); \n + * } \n + * + * - Add custom VBUS monitoring \n + * // Authorize VBUS monitoring \n + * if (!udc_include_vbus_monitoring()) { \n + * // Implement custom VBUS monitoring via GPIO or other \n + * } \n + * Event_VBUS_present() // VBUS interrupt or GPIO interrupt or other \n + * { \n + * // Attach USB Device \n + * udc_attach(); \n + * } \n + * + * - Case of battery charging \n + * Event VBUS present() // VBUS interrupt or GPIO interrupt or .. \n + * { \n + * // Authorize battery charging, but wait key press to start USB. \n + * } \n + * Event Key press() \n + * { \n + * // Stop batteries charging \n + * // Start USB \n + * udc_attach(); \n + * } \n + */ +static inline bool udc_include_vbus_monitoring(void) +{ + return udd_include_vbus_monitoring(); +} + +/*! \brief Start the USB Device stack + */ +void udc_start(void); + +/*! \brief Stop the USB Device stack + */ +void udc_stop(void); + +/** + * \brief Attach device to the bus when possible + * + * \warning If a VBus control is included in driver, + * then it will attach device when an acceptable Vbus + * level from the host is detected. + */ +static inline void udc_attach(void) +{ + udd_attach(); +} + + +/** + * \brief Detaches the device from the bus + * + * The driver must remove pull-up on USB line D- or D+. + */ +static inline void udc_detach(void) +{ + udd_detach(); +} + + +/*! \brief The USB driver sends a resume signal called \e "Upstream Resume" + * This is authorized only when the remote wakeup feature is enabled by host. + */ +static inline void udc_remotewakeup(void) +{ + udd_send_remotewakeup(); +} + + +/** + * \brief Returns a pointer on the current interface descriptor + * + * \return pointer on the current interface descriptor. + */ +usb_iface_desc_t UDC_DESC_STORAGE *udc_get_interface_desc(void); + +//@} + +/** + * \ingroup usb_group + * \defgroup usb_device_group USB Stack Device + * + * This module includes USB Stack Device implementation. + * The stack is divided in three parts: + * - USB Device Controller (UDC) provides USB chapter 9 compliance + * - USB Device Interface (UDI) provides USB Class compliance + * - USB Device Driver (UDD) provides USB Driver for each Atmel MCU + + * Many USB Device applications can be implemented on Atmel MCU. + * Atmel provides many application notes for different applications: + * - AVR4900, provides general information about Device Stack + * - AVR4901, explains how to create a new class + * - AVR4902, explains how to create a composite device + * - AVR49xx, all device classes provided in ASF have an application note + * + * A basic USB knowledge is required to understand the USB Device + * Class application notes (HID,MS,CDC,PHDC,...). + * Then, to create an USB device with + * only one class provided by ASF, refer directly to the application note + * corresponding to this USB class. The USB Device application note for + * New Class and Composite is dedicated to advanced USB users. + * + * @{ + */ + +//! @} + +#ifdef __cplusplus +} +#endif + +/** + * \ingroup udc_group + * \defgroup udc_basic_use_case_setup_prereq USB Device Controller (UDC) - Prerequisites + * Common prerequisites for all USB devices. + * + * This module is based on USB device stack full interrupt driven, and supporting + * \ref sleepmgr_group sleepmgr and \ref clk_group clock services. + * + * The following procedure must be executed to setup the project correctly: + * - Specify the clock configuration: + * - XMEGA USB devices need 48MHz clock input.\n + * XMEGA USB devices need CPU frequency higher than 12MHz.\n + * You can use either an internal RC48MHz auto calibrated by Start of Frames + * or an external OSC. + * - UC3 and SAM devices without USB high speed support need 48MHz clock input.\n + * You must use a PLL and an external OSC. + * - UC3 and SAM devices with USB high speed support need 12MHz clock input.\n + * You must use an external OSC. + * - UC3 devices with USBC hardware need CPU frequency higher than 25MHz. + * - In conf_board.h, the define CONF_BOARD_USB_PORT must be added to enable USB lines. + * (Not mandatory for all boards) + * - Enable interrupts + * - Initialize the clock service + * + * The usage of \ref sleepmgr_group sleepmgr service is optional, but recommended to reduce power + * consumption: + * - Initialize the sleep manager service + * - Activate sleep mode when the application is in IDLE state + * + * \subpage udc_conf_clock. + * + * Add to the initialization code: + * \code + * sysclk_init(); + * irq_initialize_vectors(); + * cpu_irq_enable(); + * board_init(); + * sleepmgr_init(); // Optional + * \endcode + * Add to the main IDLE loop: + * \code + * sleepmgr_enter_sleep(); // Optional + * \endcode + * + */ + +/** + * \ingroup udc_group + * \defgroup udc_basic_use_case_setup_code USB Device Controller (UDC) - Example code + * Common example code for all USB devices. + * + * Content of conf_usb.h: + * \code + * #define USB_DEVICE_VENDOR_ID 0x03EB + * #define USB_DEVICE_PRODUCT_ID 0xXXXX + * #define USB_DEVICE_MAJOR_VERSION 1 + * #define USB_DEVICE_MINOR_VERSION 0 + * #define USB_DEVICE_POWER 100 + * #define USB_DEVICE_ATTR USB_CONFIG_ATTR_BUS_POWERED + * + * #define UDC_VBUS_EVENT(b_vbus_high) my_vbus_action(b_vbus_high) + * extern void my_vbus_action(bool b_high); + * \endcode + * + * Add to application C-file: + * \code + * void usb_init(void) + * { + * udc_start(); + * } + * + * void my_vbus_action(bool b_high) + * { + * if (b_high) { + * // Attach USB Device + * udc_attach(); + * } else { + * // Vbus not present + * udc_detach(); + * } + * } + * \endcode + */ + +/** + * \ingroup udc_group + * \defgroup udc_basic_use_case_setup_flow USB Device Controller (UDC) - Workflow + * Common workflow for all USB devices. + * + * -# Ensure that conf_usb.h is available and contains the following configuration + * which is the main USB device configuration: + * - \code // Vendor ID provided by USB org (ATMEL 0x03EB) + * #define USB_DEVICE_VENDOR_ID 0x03EB // Type Word + * // Product ID (Atmel PID referenced in usb_atmel.h) + * #define USB_DEVICE_PRODUCT_ID 0xXXXX // Type Word + * // Major version of the device + * #define USB_DEVICE_MAJOR_VERSION 1 // Type Byte + * // Minor version of the device + * #define USB_DEVICE_MINOR_VERSION 0 // Type Byte + * // Maximum device power (mA) + * #define USB_DEVICE_POWER 100 // Type 9-bits + * // USB attributes to enable features + * #define USB_DEVICE_ATTR USB_CONFIG_ATTR_BUS_POWERED // Flags \endcode + * - \code #define UDC_VBUS_EVENT(b_vbus_high) my_vbus_action(b_vbus_high) + * extern void my_vbus_action(bool b_high); \endcode + * \note This callback is called when USB Device cable is plugged or unplugged. + * -# Call the USB device stack start function to enable stack: + * - \code udc_start(); \endcode + * \note In case of USB dual roles (Device and Host) managed through USB OTG connector + * (USB ID pin), the call of udc_start() must be removed and replaced by uhc_start(). + * SeRefer to "AVR4950 section 6.1 Dual roles" for further information about dual roles. + * -# Connect or disconnect USB device according to Vbus state: + * - \code void my_vbus_action(bool b_high) + * { + * if (b_high) { + * // Attach USB Device + * udc_attach(); + * } else { + * // Vbus not present + * udc_detach(); + * } + * } \endcode + */ + +/** + * \page udc_conf_clock conf_clock.h examples with USB support + * + * Content of XMEGA conf_clock.h: + * \code + * // Configuration based on internal RC: + * // USB clock need of 48Mhz + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_RCOSC + * #define CONFIG_OSC_RC32_CAL 48000000UL + * #define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC OSC_ID_USBSOF + * // CPU clock need of clock > 12MHz to run with USB (Here 24MHz) + * #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC32MHZ + * #define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_2 + * #define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_1 + * \endcode + * + * Content of conf_clock.h for AT32UC3A0, AT32UC3A1, AT32UC3B devices (USBB): + * \code + * // Configuration based on 12MHz external OSC: + * #define CONFIG_PLL1_SOURCE PLL_SRC_OSC0 + * #define CONFIG_PLL1_MUL 8 + * #define CONFIG_PLL1_DIV 2 + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL1 + * #define CONFIG_USBCLK_DIV 1 // Fusb = Fsys/(2 ^ USB_div) + * \endcode + * + * Content of conf_clock.h for AT32UC3A3, AT32UC3A4 devices (USBB with high speed support): + * \code + * // Configuration based on 12MHz external OSC: + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_OSC0 + * #define CONFIG_USBCLK_DIV 1 // Fusb = Fsys/(2 ^ USB_div) + * \endcode + * + * Content of conf_clock.h for AT32UC3C, ATUCXXD, ATUCXXL3U, ATUCXXL4U devices (USBC): + * \code + * // Configuration based on 12MHz external OSC: + * #define CONFIG_PLL1_SOURCE PLL_SRC_OSC0 + * #define CONFIG_PLL1_MUL 8 + * #define CONFIG_PLL1_DIV 2 + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL1 + * #define CONFIG_USBCLK_DIV 1 // Fusb = Fsys/(2 ^ USB_div) + * // CPU clock need of clock > 25MHz to run with USBC + * #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLL1 + * \endcode + * + * Content of conf_clock.h for SAM3S, SAM3SD, SAM4S devices (UPD: USB Peripheral Device): + * \code + * // PLL1 (B) Options (Fpll = (Fclk * PLL_mul) / PLL_div) + * #define CONFIG_PLL1_SOURCE PLL_SRC_MAINCK_XTAL + * #define CONFIG_PLL1_MUL 16 + * #define CONFIG_PLL1_DIV 2 + * // USB Clock Source Options (Fusb = FpllX / USB_div) + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL1 + * #define CONFIG_USBCLK_DIV 2 + * \endcode + * + * Content of conf_clock.h for SAM3U device (UPDHS: USB Peripheral Device High Speed): + * \code + * // USB Clock Source fixed at UPLL. + * \endcode + * + * Content of conf_clock.h for SAM3X, SAM3A devices (UOTGHS: USB OTG High Speed): + * \code + * // USB Clock Source fixed at UPLL. + * #define CONFIG_USBCLK_SOURCE USBCLK_SRC_UPLL + * #define CONFIG_USBCLK_DIV 1 + * \endcode + */ + +/** + * \page udc_use_case_1 Change USB speed + * + * In this use case, the USB device is used with different USB speeds. + * + * \section udc_use_case_1_setup Setup steps + * + * Prior to implement this use case, be sure to have already + * apply the UDI module "basic use case". + * + * \section udc_use_case_1_usage Usage steps + * + * \subsection udc_use_case_1_usage_code Example code + * Content of conf_usb.h: + * \code + * #if // Low speed + * #define USB_DEVICE_LOW_SPEED + * // #define USB_DEVICE_HS_SUPPORT + * + * #elif // Full speed + * // #define USB_DEVICE_LOW_SPEED + * // #define USB_DEVICE_HS_SUPPORT + * + * #elif // High speed + * // #define USB_DEVICE_LOW_SPEED + * #define USB_DEVICE_HS_SUPPORT + * + * #endif + * \endcode + * + * \subsection udc_use_case_1_usage_flow Workflow + * -# Ensure that conf_usb.h is available and contains the following parameters + * required for a USB device low speed (1.5Mbit/s): + * - \code #define USB_DEVICE_LOW_SPEED + * //#define USB_DEVICE_HS_SUPPORT \endcode + * -# Ensure that conf_usb.h contains the following parameters + * required for a USB device full speed (12Mbit/s): + * - \code //#define USB_DEVICE_LOW_SPEED + * //#define USB_DEVICE_HS_SUPPORT \endcode + * -# Ensure that conf_usb.h contains the following parameters + * required for a USB device high speed (480Mbit/s): + * - \code //#define USB_DEVICE_LOW_SPEED + * #define USB_DEVICE_HS_SUPPORT \endcode + */ + +/** + * \page udc_use_case_2 Use USB strings + * + * In this use case, the usual USB strings is added in the USB device. + * + * \section udc_use_case_2_setup Setup steps + * Prior to implement this use case, be sure to have already + * apply the UDI module "basic use case". + * + * \section udc_use_case_2_usage Usage steps + * + * \subsection udc_use_case_2_usage_code Example code + * Content of conf_usb.h: + * \code + * #define USB_DEVICE_MANUFACTURE_NAME "Manufacture name" + * #define USB_DEVICE_PRODUCT_NAME "Product name" + * #define USB_DEVICE_SERIAL_NAME "12...EF" + * \endcode + * + * \subsection udc_use_case_2_usage_flow Workflow + * -# Ensure that conf_usb.h is available and contains the following parameters + * required to enable different USB strings: + * - \code // Static ASCII name for the manufacture + * #define USB_DEVICE_MANUFACTURE_NAME "Manufacture name" \endcode + * - \code // Static ASCII name for the product + * #define USB_DEVICE_PRODUCT_NAME "Product name" \endcode + * - \code // Static ASCII name to enable and set a serial number + * #define USB_DEVICE_SERIAL_NAME "12...EF" \endcode + */ + +/** + * \page udc_use_case_3 Use USB remote wakeup feature + * + * In this use case, the USB remote wakeup feature is enabled. + * + * \section udc_use_case_3_setup Setup steps + * Prior to implement this use case, be sure to have already + * apply the UDI module "basic use case". + * + * \section udc_use_case_3_usage Usage steps + * + * \subsection udc_use_case_3_usage_code Example code + * Content of conf_usb.h: + * \code + * #define USB_DEVICE_ATTR \ + * (USB_CONFIG_ATTR_REMOTE_WAKEUP | USB_CONFIG_ATTR_..._POWERED) + * #define UDC_REMOTEWAKEUP_ENABLE() my_callback_remotewakeup_enable() + * extern void my_callback_remotewakeup_enable(void); + * #define UDC_REMOTEWAKEUP_DISABLE() my_callback_remotewakeup_disable() + * extern void my_callback_remotewakeup_disable(void); + * \endcode + * + * Add to application C-file: + * \code + * void my_callback_remotewakeup_enable(void) + * { + * // Enable application wakeup events (e.g. enable GPIO interrupt) + * } + * void my_callback_remotewakeup_disable(void) + * { + * // Disable application wakeup events (e.g. disable GPIO interrupt) + * } + * + * void my_interrupt_event(void) + * { + * udc_remotewakeup(); + * } + * \endcode + * + * \subsection udc_use_case_3_usage_flow Workflow + * -# Ensure that conf_usb.h is available and contains the following parameters + * required to enable remote wakeup feature: + * - \code // Authorizes the remote wakeup feature + * #define USB_DEVICE_ATTR (USB_CONFIG_ATTR_REMOTE_WAKEUP | USB_CONFIG_ATTR_..._POWERED) \endcode + * - \code // Define callback called when the host enables the remotewakeup feature + * #define UDC_REMOTEWAKEUP_ENABLE() my_callback_remotewakeup_enable() + * extern void my_callback_remotewakeup_enable(void); \endcode + * - \code // Define callback called when the host disables the remotewakeup feature + * #define UDC_REMOTEWAKEUP_DISABLE() my_callback_remotewakeup_disable() + * extern void my_callback_remotewakeup_disable(void); \endcode + * -# Send a remote wakeup (USB upstream): + * - \code udc_remotewakeup(); \endcode + */ + +/** + * \page udc_use_case_4 Self power application recommendations + * + * In this use case, the USB device self power feature is enabled. + * To be USB compliance, the SELF power application requires to manage Vbus event, + * because the USB device D+/- pull-up must be disabled if the USB cable is unplugged + * (unplug = Vbus not present, pull-up disable = \ref udd_detach()). + * This use case requires that Atmel products includes a Vbus monitoring, else + * see \ref udc_include_vbus_monitoring function documentation for more example. + * + * \section udc_use_case_4_setup Setup steps + * Prior to implement this use case, be sure to have already + * apply the UDI module "basic use case". + * + * \section udc_use_case_4_usage Usage steps + * + * \subsection udc_use_case_4_usage_code Example code + * Content of conf_usb.h: + * \code + * #define USB_DEVICE_ATTR (USB_CONFIG_ATTR_SELF_POWERED) + * #define UDC_VBUS_EVENT(b_vbus_high) user_callback_vbus_action(b_vbus_high) + * extern void user_callback_vbus_action(bool b_vbus_high); + * \endcode + * + * Add to application C-file: + * \code + * void user_callback_vbus_action(bool b_vbus_high) + * { + * if (b_high) { + * // Attach USB Device + * udc_attach(); + * } else { + * // Vbus not present + * udc_detach(); + * } + * } + * \endcode + * + * \subsection udc_use_case_4_usage_flow Workflow + * -# Ensure that conf_usb.h is available and contains the following parameters + * required for USB device SELF power device: + * - \code // Authorizes the SELF power feature + * #define USB_DEVICE_ATTR (USB_CONFIG_ATTR_SELF_POWERED) \endcode + * - \code // Define callback called when the Vbus level change + * #define UDC_VBUS_EVENT(b_vbus_high) user_callback_vbus_action(b_vbus_high) + * extern void user_callback_vbus_action(bool b_vbus_high); \endcode + * -# Signal the USB device presence on USB line + * - \code udc_attach(); \endcode + * -# Remove signal of the USB device presence on USB line + * - \code udc_detach(); \endcode + */ + +/** + * \page udc_use_case_5 Bus power application recommendations + * + * In this use case, the USB device BUS power feature is enabled. + * This feature requires a correct power consumption management. + * + * \section udc_use_case_5_setup Setup steps + * Prior to implement this use case, be sure to have already + * apply the UDI module "basic use case". + * + * \section udc_use_case_5_usage Usage steps + * + * \subsection udc_use_case_5_usage_code Example code + * Content of conf_usb.h: + * \code + * #define USB_DEVICE_ATTR (USB_CONFIG_ATTR_BUS_POWERED) + * #define UDC_SUSPEND_EVENT() user_callback_suspend_action() + * extern void user_callback_suspend_action(void) + * #define UDC_RESUME_EVENT() user_callback_resume_action() + * extern void user_callback_resume_action(void) + * \endcode + * + * Add to application C-file: + * \code + * void user_callback_suspend_action(void) + * { + * // Disable hardware component to reduce power consumption + * } + * void user_callback_resume_action(void) + * { + * // Re-enable hardware component + * } + * \endcode + * + * \subsection udc_use_case_5_usage_flow Workflow + * -# Ensure that conf_usb.h is available and contains the following parameters: + * - \code // Authorizes the BUS power feature + * #define USB_DEVICE_ATTR (USB_CONFIG_ATTR_BUS_POWERED) \endcode + * - \code // Define callback called when the host suspend the USB line + * #define UDC_SUSPEND_EVENT() user_callback_suspend_action() + * extern void user_callback_suspend_action(void); \endcode + * - \code // Define callback called when the host or device resume the USB line + * #define UDC_RESUME_EVENT() user_callback_resume_action() + * extern void user_callback_resume_action(void); \endcode + * -# Reduce power consumption in suspend mode (max. 2.5mA on Vbus): + * - \code void user_callback_suspend_action(void) + * { + * turn_off_components(); + * } \endcode + */ + +/** + * \page udc_use_case_6 USB dynamic serial number + * + * In this use case, the USB serial strings is dynamic. + * For a static serial string refer to \ref udc_use_case_2. + * + * \section udc_use_case_6_setup Setup steps + * Prior to implement this use case, be sure to have already + * apply the UDI module "basic use case". + * + * \section udc_use_case_6_usage Usage steps + * + * \subsection udc_use_case_6_usage_code Example code + * Content of conf_usb.h: + * \code + * #define USB_DEVICE_SERIAL_NAME + * #define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number + * #define USB_DEVICE_GET_SERIAL_NAME_LENGTH 12 + * extern uint8_t serial_number[]; + * \endcode + * + * Add to application C-file: + * \code + * uint8_t serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + * + * void init_build_usb_serial_number(void) + * { + * serial_number[0] = 'A'; + * serial_number[1] = 'B'; + * ... + * serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH-1] = 'C'; + * } \endcode + * + * \subsection udc_use_case_6_usage_flow Workflow + * -# Ensure that conf_usb.h is available and contains the following parameters + * required to enable a USB serial number strings dynamically: + * - \code #define USB_DEVICE_SERIAL_NAME // Define this empty + * #define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number // Give serial array pointer + * #define USB_DEVICE_GET_SERIAL_NAME_LENGTH 12 // Give size of serial array + * extern uint8_t serial_number[]; // Declare external serial array \endcode + * -# Before start USB stack, initialize the serial array + * - \code + * uint8_t serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + * + * void init_build_usb_serial_number(void) + * { + * serial_number[0] = 'A'; + * serial_number[1] = 'B'; + * ... + * serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH-1] = 'C'; + * } \endcode + */ + + + +#endif // _UDC_H_ diff --git a/DSTAT-temp/src/asf/common/services/usb/udc/udc_desc.h b/DSTAT-temp/src/asf/common/services/usb/udc/udc_desc.h new file mode 100644 index 0000000..294ee10 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/udc/udc_desc.h @@ -0,0 +1,131 @@ +/** + * \file + * + * \brief Common API for USB Device Interface + * + * Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _UDC_DESC_H_ +#define _UDC_DESC_H_ + +#include "conf_usb.h" +#include "usb_protocol.h" +#include "udi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \ingroup udc_group + * \defgroup udc_desc_group USB Device Descriptor + * + * @{ + */ + +/** + * \brief Defines the memory's location of USB descriptors + * + * By default the Descriptor is stored in RAM + * (UDC_DESC_STORAGE is defined empty). + * + * If you have need to free RAM space, + * it is possible to put descriptor in flash in following case: + * - USB driver authorize flash transfer (USBB on UC3 and USB on Mega) + * - USB Device is not high speed (UDC no need to change USB descriptors) + * + * For UC3 application used "const". + * + * For Mega application used "code". + */ +#define UDC_DESC_STORAGE + // Descriptor storage in internal RAM +#if (defined UDC_DATA_USE_HRAM_SUPPORT) +# if defined(__GNUC__) +# define UDC_DATA(x) COMPILER_WORD_ALIGNED __attribute__((__section__(".data_hram0"))) +# define UDC_BSS(x) COMPILER_ALIGNED(x) __attribute__((__section__(".bss_hram0"))) +# elif defined(__ICCAVR32__) +# define UDC_DATA(x) COMPILER_ALIGNED(x) __data32 +# define UDC_BSS(x) COMPILER_ALIGNED(x) __data32 +# endif +#else +# define UDC_DATA(x) COMPILER_ALIGNED(x) +# define UDC_BSS(x) COMPILER_ALIGNED(x) +#endif + + + +/** + * \brief Configuration descriptor and UDI link for one USB speed + */ +typedef struct { + //! USB configuration descriptor + usb_conf_desc_t UDC_DESC_STORAGE *desc; + //! Array of UDI API pointer + udi_api_t UDC_DESC_STORAGE *UDC_DESC_STORAGE * udi_apis; +} udc_config_speed_t; + + +/** + * \brief All information about the USB Device + */ +typedef struct { + //! USB device descriptor for low or full speed + usb_dev_desc_t UDC_DESC_STORAGE *confdev_lsfs; + //! USB configuration descriptor and UDI API pointers for low or full speed + udc_config_speed_t UDC_DESC_STORAGE *conf_lsfs; +#ifdef USB_DEVICE_HS_SUPPORT + //! USB device descriptor for high speed + usb_dev_desc_t UDC_DESC_STORAGE *confdev_hs; + //! USB device qualifier, only use in high speed mode + usb_dev_qual_desc_t UDC_DESC_STORAGE *qualifier; + //! USB configuration descriptor and UDI API pointers for high speed + udc_config_speed_t UDC_DESC_STORAGE *conf_hs; +#endif +} udc_config_t; + +//! Global variables of USB Device Descriptor and UDI links +extern UDC_DESC_STORAGE udc_config_t udc_config; + +//@} + +#ifdef __cplusplus +} +#endif +#endif // _UDC_DESC_H_ diff --git a/DSTAT-temp/src/asf/common/services/usb/udc/udd.h b/DSTAT-temp/src/asf/common/services/usb/udc/udd.h new file mode 100644 index 0000000..cba4814 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/udc/udd.h @@ -0,0 +1,392 @@ +/** + * \file + * + * \brief Common API for USB Device Drivers (UDD) + * + * Copyright (c) 2009 - 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _UDD_H_ +#define _UDD_H_ + +#include "usb_protocol.h" +#include "udc_desc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \ingroup usb_device_group + * \defgroup udd_group USB Device Driver (UDD) + * + * The UDD driver provides a low-level abstraction of the device + * controller hardware. Most events coming from the hardware such as + * interrupts, which may cause the UDD to call into the UDC and UDI. + * + * @{ + */ + +//! \brief Endpoint identifier +typedef uint8_t udd_ep_id_t; + +//! \brief Endpoint transfer status +//! Returned in parameters of callback register via udd_ep_run routine. +typedef enum { + UDD_EP_TRANSFER_OK = 0, + UDD_EP_TRANSFER_ABORT = 1, +} udd_ep_status_t; + +/** + * \brief Global variable to give and record information of the setup request management + * + * This global variable allows to decode and response a setup request. + * It can be updated by udc_process_setup() from UDC or *setup() from UDIs. + */ +typedef struct { + //! Data received in USB SETUP packet + //! Note: The swap of "req.wValues" from uin16_t to le16_t is done by UDD. + usb_setup_req_t req; + + //! Point to buffer to send or fill with data following SETUP packet + uint8_t *payload; + + //! Size of buffer to send or fill, and content the number of byte transfered + uint16_t payload_size; + + //! Callback called after reception of ZLP from setup request + void (*callback) (void); + + //! Callback called when the buffer given (.payload) is full or empty. + //! This one return false to abort data transfer, or true with a new buffer in .payload. + bool(*over_under_run) (void); +} udd_ctrl_request_t; +extern udd_ctrl_request_t udd_g_ctrlreq; + +//! Return true if the setup request \a udd_g_ctrlreq indicates IN data transfer +#define Udd_setup_is_in() \ + (USB_REQ_DIR_IN == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK)) + +//! Return true if the setup request \a udd_g_ctrlreq indicates OUT data transfer +#define Udd_setup_is_out() \ + (USB_REQ_DIR_OUT == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK)) + +//! Return the type of the SETUP request \a udd_g_ctrlreq. \see usb_reqtype. +#define Udd_setup_type() \ + (udd_g_ctrlreq.req.bmRequestType & USB_REQ_TYPE_MASK) + +//! Return the recipient of the SETUP request \a udd_g_ctrlreq. \see usb_recipient +#define Udd_setup_recipient() \ + (udd_g_ctrlreq.req.bmRequestType & USB_REQ_RECIP_MASK) + +/** + * \brief End of halt callback function type. + * Registered by routine udd_ep_wait_stall_clear() + * Callback called when endpoint stall is cleared. + */ +typedef void (*udd_callback_halt_cleared_t) (void); + +/** + * \brief End of transfer callback function type. + * Registered by routine udd_ep_run() + * Callback called by USB interrupt after data transfer or abort (reset,...). + * + * \param status UDD_EP_TRANSFER_OK, if transfer is complete + * \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted + * \param n number of data transfered + */ +typedef void (*udd_callback_trans_t) (udd_ep_status_t status, + iram_size_t nb_transfered, udd_ep_id_t ep); + +/** + * \brief Authorizes the VBUS event + * + * \return true, if the VBUS monitoring is possible. + */ +bool udd_include_vbus_monitoring(void); + +/** + * \brief Enables the USB Device mode + */ +void udd_enable(void); + +/** + * \brief Disables the USB Device mode + */ +void udd_disable(void); + +/** + * \brief Attach device to the bus when possible + * + * \warning If a VBus control is included in driver, + * then it will attach device when an acceptable Vbus + * level from the host is detected. + */ +void udd_attach(void); + +/** + * \brief Detaches the device from the bus + * + * The driver must remove pull-up on USB line D- or D+. + */ +void udd_detach(void); + +/** + * \brief Test whether the USB Device Controller is running at high + * speed or not. + * + * \return \c true if the Device is running at high speed mode, otherwise \c false. + */ +bool udd_is_high_speed(void); + +/** + * \brief Changes the USB address of device + * + * \param address New USB address + */ +void udd_set_address(uint8_t address); + +/** + * \brief Returns the USB address of device + * + * \return USB address + */ +uint8_t udd_getaddress(void); + +/** + * \brief Returns the current start of frame number + * + * \return current start of frame number. + */ +uint16_t udd_get_frame_number(void); + +/** + * \brief Returns the current micro start of frame number + * + * \return current micro start of frame number required in high speed mode. + */ +uint16_t udd_get_micro_frame_number(void); + +/*! \brief The USB driver sends a resume signal called Upstream Resume + */ +void udd_send_remotewakeup(void); + +/** + * \brief Load setup payload + * + * \param payload Pointer on payload + * \param payload_size Size of payload + */ +void udd_set_setup_payload( uint8_t *payload, uint16_t payload_size ); + + +/** + * \name Endpoint Management + * + * The following functions allow drivers to create and remove + * endpoints, as well as set, clear and query their "halted" and + * "wedged" states. + */ +//@{ + +#if (USB_DEVICE_MAX_EP != 0) + +/** + * \brief Configures and enables an endpoint + * + * \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT). + * \param bmAttributes Attributes of endpoint declared in the descriptor. + * \param MaxEndpointSize Endpoint maximum size + * + * \return \c 1 if the endpoint is enabled, otherwise \c 0. + */ +bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes, + uint16_t MaxEndpointSize); + +/** + * \brief Disables an endpoint + * + * \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT). + */ +void udd_ep_free(udd_ep_id_t ep); + +/** + * \brief Check if the endpoint \a ep is halted. + * + * \param ep The ID of the endpoint to check. + * + * \return \c 1 if \a ep is halted, otherwise \c 0. + */ +bool udd_ep_is_halted(udd_ep_id_t ep); + +/** + * \brief Set the halted state of the endpoint \a ep + * + * After calling this function, any transaction on \a ep will result + * in a STALL handshake being sent. Any pending transactions will be + * performed first, however. + * + * \param ep The ID of the endpoint to be halted + * + * \return \c 1 if \a ep is halted, otherwise \c 0. + */ +bool udd_ep_set_halt(udd_ep_id_t ep); + +/** + * \brief Clear the halted state of the endpoint \a ep + * + * After calling this function, any transaction on \a ep will + * be handled normally, i.e. a STALL handshake will not be sent, and + * the data toggle sequence will start at DATA0. + * + * \param ep The ID of the endpoint to be un-halted + * + * \return \c 1 if function was successfully done, otherwise \c 0. + */ +bool udd_ep_clear_halt(udd_ep_id_t ep); + +/** + * \brief Registers a callback to call when endpoint halt is cleared + * + * \param ep The ID of the endpoint to use + * \param callback NULL or function to call when endpoint halt is cleared + * + * \warning if the endpoint is not halted then the \a callback is called immediately. + * + * \return \c 1 if the register is accepted, otherwise \c 0. + */ +bool udd_ep_wait_stall_clear(udd_ep_id_t ep, + udd_callback_halt_cleared_t callback); + +/** + * \brief Allows to receive or send data on an endpoint + * + * The driver uses a specific DMA USB to transfer data + * from internal RAM to endpoint, if this one is available. + * When the transfer is finished or aborted (stall, reset, ...), the \a callback is called. + * The \a callback returns the transfer status and eventually the number of byte transfered. + * Note: The control endpoint is not authorized. + * + * \param ep The ID of the endpoint to use + * \param b_shortpacket Enabled automatic short packet + * \param buf Buffer on Internal RAM to send or fill. + * It must be align, then use COMPILER_WORD_ALIGNED. + * \param buf_size Buffer size to send or fill + * \param callback NULL or function to call at the end of transfer + * + * \warning About \a b_shortpacket, for IN endpoint it means that a short packet + * (or a Zero Length Packet) will be sent to the USB line to properly close the usb + * transfer at the end of the data transfer. + * For Bulk and Interrupt OUT endpoint, it will automatically stop the transfer + * at the end of the data transfer (received short packet). + * + * \return \c 1 if function was successfully done, otherwise \c 0. + */ +bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket, + uint8_t * buf, iram_size_t buf_size, + udd_callback_trans_t callback); +/** + * \brief Aborts transfer on going on endpoint + * + * If a transfer is on going, then it is stopped and + * the callback registered is called to signal the end of transfer. + * Note: The control endpoint is not authorized. + * + * \param ep Endpoint to abort + */ +void udd_ep_abort(udd_ep_id_t ep); + +#endif + +//@} + + +/** + * \name High speed test mode management + * + * The following functions allow the device to jump to a specific test mode required in high speed mode. + */ +//@{ +void udd_test_mode_j(void); +void udd_test_mode_k(void); +void udd_test_mode_se0_nak(void); +void udd_test_mode_packet(void); +//@} + + +/** + * \name UDC callbacks to provide for UDD + * + * The following callbacks are used by UDD. + */ +//@{ + +/** + * \brief Decodes and manages a setup request + * + * The driver call it when a SETUP packet is received. + * The \c udd_g_ctrlreq contains the data of SETUP packet. + * If this callback accepts the setup request then it must + * return \c 1 and eventually update \c udd_g_ctrlreq to send or receive data. + * + * \return \c 1 if the request is accepted, otherwise \c 0. + */ +extern bool udc_process_setup(void); + +/** + * \brief Reset the UDC + * + * The UDC must reset all configuration. + */ +extern void udc_reset(void); + +/** + * \brief To signal that a SOF is occurred + * + * The UDC must send the signal to all UDIs enabled + */ +extern void udc_sof_notify(void); + +//@} + +//@} + +#ifdef __cplusplus +} +#endif +#endif // _UDD_H_ diff --git a/DSTAT-temp/src/asf/common/services/usb/udc/udi.h b/DSTAT-temp/src/asf/common/services/usb/udc/udi.h new file mode 100644 index 0000000..48287f2 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/udc/udi.h @@ -0,0 +1,130 @@ +/** + * \file + * + * \brief Common API for USB Device Interface + * + * Copyright (c) 2009 - 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _UDI_H_ +#define _UDI_H_ + +#include "conf_usb.h" +#include "usb_protocol.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \ingroup usb_device_group + * \defgroup udi_group USB Device Interface (UDI) + * The UDI provides a common API for all classes, + * and this is used by UDC for the main control of USB Device interface. + * @{ + */ + +/** + * \brief UDI API. + * + * The callbacks within this structure are called only by + * USB Device Controller (UDC) + * + * The udc_get_interface_desc() can be use by UDI to know the interface descriptor + * selected by UDC. + */ +typedef struct { + /** + * \brief Enable the interface. + * + * This function is called when the host selects a configuration + * to which this interface belongs through a Set Configuration + * request, and when the host selects an alternate setting of + * this interface through a Set Interface request. + * + * \return \c 1 if function was successfully done, otherwise \c 0. + */ + bool(*enable) (void); + + /** + * \brief Disable the interface. + * + * This function is called when this interface is currently + * active, and + * - the host selects any configuration through a Set + * Configuration request, or + * - the host issues a USB reset, or + * - the device is detached from the host (i.e. Vbus is no + * longer present) + */ + void (*disable) (void); + + /** + * \brief Handle a control request directed at an interface. + * + * This function is called when this interface is currently + * active and the host sends a SETUP request + * with this interface as the recipient. + * + * Use udd_g_ctrlreq to decode and response to SETUP request. + * + * \return \c 1 if this interface supports the SETUP request, otherwise \c 0. + */ + bool(*setup) (void); + + /** + * \brief Returns the current setting of the selected interface. + * + * This function is called when UDC when know alternate setting of selected interface. + * + * \return alternate setting of selected interface + */ + uint8_t(*getsetting) (void); + + /** + * \brief To signal that a SOF is occurred + */ + void(*sof_notify) (void); +} udi_api_t; + +//@} + +#ifdef __cplusplus +} +#endif +#endif // _UDI_H_ diff --git a/DSTAT-temp/src/asf/common/services/usb/usb_atmel.h b/DSTAT-temp/src/asf/common/services/usb/usb_atmel.h new file mode 100644 index 0000000..8d547b4 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/usb_atmel.h @@ -0,0 +1,185 @@ +/** + * \file + * + * \brief All USB VIDs and PIDs from Atmel USB applications + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _USB_ATMEL_H_ +#define _USB_ATMEL_H_ + +/** + * \defgroup usb_group USB Stack + * + * This stack includes the USB Device Stack, USB Host Stack and common + * definitions. + * @{ + */ + +//! @} + +/** + * \ingroup usb_group + * \defgroup usb_atmel_ids_group Atmel USB Identifiers + * + * This module defines Atmel PID and VIDs constants. + * + * @{ + */ + +//! \name Vendor Identifier assigned by USB org to ATMEL +#define USB_VID_ATMEL 0x03EB + + +//! \name Product Identifier assigned by ATMEL to AVR applications +//! @{ + +//! \name The range from 2000h to 20FFh is reserved to the old PID for C51, MEGA, and others. +//! @{ +#define USB_PID_ATMEL_MEGA_HIDGENERIC 0x2013 +#define USB_PID_ATMEL_MEGA_HIDKEYBOARD 0x2017 +#define USB_PID_ATMEL_MEGA_CDC 0x2018 +#define USB_PID_ATMEL_MEGA_AUDIO_IN 0x2019 +#define USB_PID_ATMEL_MEGA_MS 0x201A +#define USB_PID_ATMEL_MEGA_AUDIO_IN_OUT 0x201B +#define USB_PID_ATMEL_MEGA_HIDMOUSE 0x201C +#define USB_PID_ATMEL_MEGA_HIDMOUSE_CERTIF_U4 0x201D +#define USB_PID_ATMEL_MEGA_CDC_MULTI 0x201E +#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_USBKEY 0x2022 +#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_STK525 0x2023 +#define USB_PID_ATMEL_MEGA_MS_2 0x2029 +#define USB_PID_ATMEL_MEGA_MS_HIDMS 0x202A +#define USB_PID_ATMEL_MEGA_MS_3 0x2032 +#define USB_PID_ATMEL_MEGA_LIBUSB 0x2050 +//! @} + +//! \name The range 2100h to 21FFh is reserved to PIDs for AVR Tools. +//! @{ +#define USB_PID_ATMEL_XPLAINED 0x2122 +//! @} + +//! \name The range 2300h to 23FFh is reserved to PIDs for demo from ASF1.7=> +//! @{ +#define USB_PID_ATMEL_UC3_ENUM 0x2300 +#define USB_PID_ATMEL_UC3_MS 0x2301 +#define USB_PID_ATMEL_UC3_MS_SDRAM_LOADER 0x2302 +#define USB_PID_ATMEL_UC3_EVK1100_CTRLPANEL 0x2303 +#define USB_PID_ATMEL_UC3_HID 0x2304 +#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID 0x2305 +#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID_MS 0x2306 +#define USB_PID_ATMEL_UC3_CDC 0x2307 +#define USB_PID_ATMEL_UC3_AUDIO_MICRO 0x2308 +#define USB_PID_ATMEL_UC3_CDC_DEBUG 0x2310 // Virtual Com (debug interface) on EVK11xx +#define USB_PID_ATMEL_UC3_AUDIO_SPEAKER_MICRO 0x2311 +#define USB_PID_ATMEL_UC3_CDC_MSC 0x2312 +//! @} + +//! \name The range 2400h to 24FFh is reserved to PIDs for ASF applications +//! @{ +#define USB_PID_ATMEL_ASF_HIDMOUSE 0x2400 +#define USB_PID_ATMEL_ASF_HIDKEYBOARD 0x2401 +#define USB_PID_ATMEL_ASF_HIDGENERIC 0x2402 +#define USB_PID_ATMEL_ASF_MSC 0x2403 +#define USB_PID_ATMEL_ASF_CDC 0x2404 +#define USB_PID_ATMEL_ASF_PHDC 0x2405 +#define USB_PID_ATMEL_ASF_MSC_HIDMOUSE 0x2420 +#define USB_PID_ATMEL_ASF_MSC_HIDS_CDC 0x2421 +#define USB_PID_ATMEL_ASF_MSC_HIDKEYBOARD 0x2422 +#define USB_PID_ATMEL_ASF_VENDOR_CLASS 0x2423 +#define USB_PID_ATMEL_ASF_MSC_CDC 0x2424 +#define USB_PID_ATMEL_ASF_TWO_CDC 0x2425 +#define USB_PID_ATMEL_ASF_SEVEN_CDC 0x2426 +#define USB_PID_ATMEL_ASF_XPLAIN_BC_POWERONLY 0x2430 +#define USB_PID_ATMEL_ASF_XPLAIN_BC_TERMINAL 0x2431 +#define USB_PID_ATMEL_ASF_XPLAIN_BC_TOUCH 0x2432 +#define USB_PID_ATMEL_ASF_AUDIO_SPEAKER 0x2433 +#define USB_PID_ATMEL_ASF_XMEGA_B1_XPLAINED 0x2434 +//! @} + +//! \name The range 2F00h to 2FFFh is reserved to official PIDs for AVR bootloaders +//! Note, !!!! don't use this range for demos or examples !!!! +//! @{ +#define USB_PID_ATMEL_DFU_ATXMEGA64C3 0x2FD6 +#define USB_PID_ATMEL_DFU_ATXMEGA128C3 0x2FD7 +#define USB_PID_ATMEL_DFU_ATXMEGA16C4 0x2FD8 +#define USB_PID_ATMEL_DFU_ATXMEGA32C4 0x2FD9 +#define USB_PID_ATMEL_DFU_ATXMEGA256C3 0x2FDA +#define USB_PID_ATMEL_DFU_ATXMEGA384C3 0x2FDB +#define USB_PID_ATMEL_DFU_ATUCL3_L4 0x2FDC +#define USB_PID_ATMEL_DFU_ATXMEGA64A4U 0x2FDD +#define USB_PID_ATMEL_DFU_ATXMEGA128A4U 0x2FDE + +#define USB_PID_ATMEL_DFU_ATXMEGA64B3 0x2FDF +#define USB_PID_ATMEL_DFU_ATXMEGA128B3 0x2FE0 +#define USB_PID_ATMEL_DFU_ATXMEGA64B1 0x2FE1 +#define USB_PID_ATMEL_DFU_ATXMEGA256A3BU 0x2FE2 +#define USB_PID_ATMEL_DFU_ATXMEGA16A4U 0x2FE3 +#define USB_PID_ATMEL_DFU_ATXMEGA32A4U 0x2FE4 +#define USB_PID_ATMEL_DFU_ATXMEGA64A3U 0x2FE5 +#define USB_PID_ATMEL_DFU_ATXMEGA128A3U 0x2FE6 +#define USB_PID_ATMEL_DFU_ATXMEGA192A3U 0x2FE7 +#define USB_PID_ATMEL_DFU_ATXMEGA64A1U 0x2FE8 +#define USB_PID_ATMEL_DFU_ATUC3D 0x2FE9 +#define USB_PID_ATMEL_DFU_ATXMEGA128B1 0x2FEA +#define USB_PID_ATMEL_DFU_AT32UC3C 0x2FEB +#define USB_PID_ATMEL_DFU_ATXMEGA256A3U 0x2FEC +#define USB_PID_ATMEL_DFU_ATXMEGA128A1U 0x2FED +#define USB_PID_ATMEL_DFU_ATMEGA8U2 0x2FEE +#define USB_PID_ATMEL_DFU_ATMEGA16U2 0x2FEF +#define USB_PID_ATMEL_DFU_ATMEGA32U2 0x2FF0 +#define USB_PID_ATMEL_DFU_AT32UC3A3 0x2FF1 +#define USB_PID_ATMEL_DFU_ATMEGA32U6 0x2FF2 +#define USB_PID_ATMEL_DFU_ATMEGA16U4 0x2FF3 +#define USB_PID_ATMEL_DFU_ATMEGA32U4 0x2FF4 +#define USB_PID_ATMEL_DFU_AT32AP7200 0x2FF5 +#define USB_PID_ATMEL_DFU_AT32UC3B 0x2FF6 +#define USB_PID_ATMEL_DFU_AT90USB82 0x2FF7 +#define USB_PID_ATMEL_DFU_AT32UC3A 0x2FF8 +#define USB_PID_ATMEL_DFU_AT90USB64 0x2FF9 +#define USB_PID_ATMEL_DFU_AT90USB162 0x2FFA +#define USB_PID_ATMEL_DFU_AT90USB128 0x2FFB +// 2FFCh to 2FFFh used by C51 family products +//! @} + +//! @} + +//! @} + + +#endif // _USB_ATMEL_H_ diff --git a/DSTAT-temp/src/asf/common/services/usb/usb_protocol.h b/DSTAT-temp/src/asf/common/services/usb/usb_protocol.h new file mode 100644 index 0000000..1f0d3f2 --- /dev/null +++ b/DSTAT-temp/src/asf/common/services/usb/usb_protocol.h @@ -0,0 +1,410 @@ +/** + * \file + * + * \brief USB protocol definitions. + * + * This file contains the USB definitions and data structures provided by the + * USB 2.0 specification. + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _USB_PROTOCOL_H_ +#define _USB_PROTOCOL_H_ + +#include "usb_atmel.h" + +/** + * \ingroup usb_group + * \defgroup usb_protocol_group USB Protocol Definitions + * + * This module defines constants and data structures provided by the USB + * 2.0 specification. + * + * @{ + */ + +//! Value for field bcdUSB +#define USB_V2_0 0x0200 //!< USB Specification version 2.00 + +/*! \name Generic definitions (Class, subclass and protocol) + */ +//! @{ +#define NO_CLASS 0x00 +#define CLASS_VENDOR_SPECIFIC 0xFF +#define NO_SUBCLASS 0x00 +#define NO_PROTOCOL 0x00 +//! @} + +//! \name IAD (Interface Association Descriptor) constants +//! @{ +#define CLASS_IAD 0xEF +#define SUB_CLASS_IAD 0x02 +#define PROTOCOL_IAD 0x01 +//! @} + +/** + * \brief USB request data transfer direction (bmRequestType) + */ +#define USB_REQ_DIR_OUT (0<<7) //!< Host to device +#define USB_REQ_DIR_IN (1<<7) //!< Device to host +#define USB_REQ_DIR_MASK (1<<7) //!< Mask + +/** + * \brief USB request types (bmRequestType) + */ +#define USB_REQ_TYPE_STANDARD (0<<5) //!< Standard request +#define USB_REQ_TYPE_CLASS (1<<5) //!< Class-specific request +#define USB_REQ_TYPE_VENDOR (2<<5) //!< Vendor-specific request +#define USB_REQ_TYPE_MASK (3<<5) //!< Mask + +/** + * \brief USB recipient codes (bmRequestType) + */ +#define USB_REQ_RECIP_DEVICE (0<<0) //!< Recipient device +#define USB_REQ_RECIP_INTERFACE (1<<0) //!< Recipient interface +#define USB_REQ_RECIP_ENDPOINT (2<<0) //!< Recipient endpoint +#define USB_REQ_RECIP_OTHER (3<<0) //!< Recipient other +#define USB_REQ_RECIP_MASK (0x1F) //!< Mask + +/** + * \brief Standard USB requests (bRequest) + */ +enum usb_reqid { + USB_REQ_GET_STATUS = 0, + USB_REQ_CLEAR_FEATURE = 1, + USB_REQ_SET_FEATURE = 3, + USB_REQ_SET_ADDRESS = 5, + USB_REQ_GET_DESCRIPTOR = 6, + USB_REQ_SET_DESCRIPTOR = 7, + USB_REQ_GET_CONFIGURATION = 8, + USB_REQ_SET_CONFIGURATION = 9, + USB_REQ_GET_INTERFACE = 10, + USB_REQ_SET_INTERFACE = 11, + USB_REQ_SYNCH_FRAME = 12, +}; + +/** + * \brief Standard USB device status flags + * + */ +enum usb_device_status { + USB_DEV_STATUS_BUS_POWERED = 0, + USB_DEV_STATUS_SELF_POWERED = 1, + USB_DEV_STATUS_REMOTEWAKEUP = 2 +}; + +/** + * \brief Standard USB Interface status flags + * + */ +enum usb_interface_status { + USB_IFACE_STATUS_RESERVED = 0 +}; + +/** + * \brief Standard USB endpoint status flags + * + */ +enum usb_endpoint_status { + USB_EP_STATUS_HALTED = 1, +}; + +/** + * \brief Standard USB device feature flags + * + * \note valid for SetFeature request. + */ +enum usb_device_feature { + USB_DEV_FEATURE_REMOTE_WAKEUP = 1, //!< Remote wakeup enabled + USB_DEV_FEATURE_TEST_MODE = 2, //!< USB test mode + USB_DEV_FEATURE_OTG_B_HNP_ENABLE = 3, + USB_DEV_FEATURE_OTG_A_HNP_SUPPORT = 4, + USB_DEV_FEATURE_OTG_A_ALT_HNP_SUPPORT = 5 +}; + +/** + * \brief Test Mode possible on HS USB device + * + * \note valid for USB_DEV_FEATURE_TEST_MODE request. + */ +enum usb_device_hs_test_mode { + USB_DEV_TEST_MODE_J = 1, + USB_DEV_TEST_MODE_K = 2, + USB_DEV_TEST_MODE_SE0_NAK = 3, + USB_DEV_TEST_MODE_PACKET = 4, + USB_DEV_TEST_MODE_FORCE_ENABLE = 5, +}; + +/** + * \brief Standard USB endpoint feature/status flags + */ +enum usb_endpoint_feature { + USB_EP_FEATURE_HALT = 0, +}; + +/** + * \brief Standard USB Test Mode Selectors + */ +enum usb_test_mode_selector { + USB_TEST_J = 0x01, + USB_TEST_K = 0x02, + USB_TEST_SE0_NAK = 0x03, + USB_TEST_PACKET = 0x04, + USB_TEST_FORCE_ENABLE = 0x05, +}; + +/** + * \brief Standard USB descriptor types + */ +enum usb_descriptor_type { + USB_DT_DEVICE = 1, + USB_DT_CONFIGURATION = 2, + USB_DT_STRING = 3, + USB_DT_INTERFACE = 4, + USB_DT_ENDPOINT = 5, + USB_DT_DEVICE_QUALIFIER = 6, + USB_DT_OTHER_SPEED_CONFIGURATION = 7, + USB_DT_INTERFACE_POWER = 8, + USB_DT_OTG = 9, + USB_DT_IAD = 0x0B, +}; + +/** + * \brief Standard USB endpoint transfer types + */ +enum usb_ep_type { + USB_EP_TYPE_CONTROL = 0x00, + USB_EP_TYPE_ISOCHRONOUS = 0x01, + USB_EP_TYPE_BULK = 0x02, + USB_EP_TYPE_INTERRUPT = 0x03, + USB_EP_TYPE_MASK = 0x03, +}; + +/** + * \brief Standard USB language IDs for string descriptors + */ +enum usb_langid { + USB_LANGID_EN_US = 0x0409, //!< English (United States) +}; + +/** + * \brief Mask selecting the index part of an endpoint address + */ +#define USB_EP_ADDR_MASK 0x0f + +//! \brief USB address identifier +typedef uint8_t usb_add_t; + +/** + * \brief Endpoint transfer direction is IN + */ +#define USB_EP_DIR_IN 0x80 + +/** + * \brief Endpoint transfer direction is OUT + */ +#define USB_EP_DIR_OUT 0x00 + +//! \brief Endpoint identifier +typedef uint8_t usb_ep_t; + +/** + * \brief Maximum length in bytes of a USB descriptor + * + * The maximum length of a USB descriptor is limited by the 8-bit + * bLength field. + */ +#define USB_MAX_DESC_LEN 255 + +/* + * 2-byte alignment requested for all USB structures. + */ +COMPILER_PACK_SET(1) + +/** + * \brief A USB Device SETUP request + * + * The data payload of SETUP packets always follows this structure. + */ +typedef struct { + uint8_t bmRequestType; + uint8_t bRequest; + le16_t wValue; + le16_t wIndex; + le16_t wLength; +} usb_setup_req_t; + +/** + * \brief Standard USB device descriptor structure + */ +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + le16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + le16_t idVendor; + le16_t idProduct; + le16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} usb_dev_desc_t; + +/** + * \brief Standard USB device qualifier descriptor structure + * + * This descriptor contains information about the device when running at + * the "other" speed (i.e. if the device is currently operating at high + * speed, this descriptor can be used to determine what would change if + * the device was operating at full speed.) + */ +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + le16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t bNumConfigurations; + uint8_t bReserved; +} usb_dev_qual_desc_t; + + +/** + * \brief Standard USB Interface Association Descriptor structure + */ +typedef struct { + uint8_t bLength; //!< size of this descriptor in bytes + uint8_t bDescriptorType; //!< INTERFACE descriptor type + uint8_t bFirstInterface; //!< Number of interface + uint8_t bInterfaceCount; //!< value to select alternate setting + uint8_t bFunctionClass; //!< Class code assigned by the USB + uint8_t bFunctionSubClass;//!< Sub-class code assigned by the USB + uint8_t bFunctionProtocol;//!< Protocol code assigned by the USB + uint8_t iFunction; //!< Index of string descriptor +} usb_association_desc_t; + + +/** + * \brief Standard USB configuration descriptor structure + */ +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + le16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} usb_conf_desc_t; + + +#define USB_CONFIG_ATTR_MUST_SET (1 << 7) //!< Must always be set +#define USB_CONFIG_ATTR_BUS_POWERED (0 << 6) //!< Bus-powered +#define USB_CONFIG_ATTR_SELF_POWERED (1 << 6) //!< Self-powered +#define USB_CONFIG_ATTR_REMOTE_WAKEUP (1 << 5) //!< remote wakeup supported + +#define USB_CONFIG_MAX_POWER(ma) (((ma) + 1) / 2) //!< Max power in mA + +/** + * \brief Standard USB association descriptor structure + */ +typedef struct { + uint8_t bLength; //!< Size of this descriptor in bytes + uint8_t bDescriptorType; //!< Interface descriptor type + uint8_t bFirstInterface; //!< Number of interface + uint8_t bInterfaceCount; //!< value to select alternate setting + uint8_t bFunctionClass; //!< Class code assigned by the USB + uint8_t bFunctionSubClass; //!< Sub-class code assigned by the USB + uint8_t bFunctionProtocol; //!< Protocol code assigned by the USB + uint8_t iFunction; //!< Index of string descriptor +} usb_iad_desc_t; + +/** + * \brief Standard USB interface descriptor structure + */ +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} usb_iface_desc_t; + +/** + * \brief Standard USB endpoint descriptor structure + */ +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + le16_t wMaxPacketSize; + uint8_t bInterval; +} usb_ep_desc_t; + + +/** + * \brief A standard USB string descriptor structure + */ +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; +} usb_str_desc_t; + +typedef struct { + usb_str_desc_t desc; + le16_t string[1]; +} usb_str_lgid_desc_t; + +COMPILER_PACK_RESET() + +//! @} + +#endif /* _USB_PROTOCOL_H_ */ diff --git a/DSTAT-temp/src/asf/common/utils/interrupt.h b/DSTAT-temp/src/asf/common/utils/interrupt.h new file mode 100644 index 0000000..3309b53 --- /dev/null +++ b/DSTAT-temp/src/asf/common/utils/interrupt.h @@ -0,0 +1,139 @@ +/** + * \file + * + * \brief Global interrupt management for 8- and 32-bit AVR + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef UTILS_INTERRUPT_H +#define UTILS_INTERRUPT_H + +#include + +#if XMEGA || MEGA +# include "interrupt/interrupt_avr8.h" +#elif UC3 +# include "interrupt/interrupt_avr32.h" +#elif SAM3S || SAM3N || SAM3XA || SAM3U || SAM4S || SAM4L +# include "interrupt/interrupt_sam_nvic.h" +#else +# error Unsupported device. +#endif + +/** + * \defgroup interrupt_group Global interrupt management + * + * This is a driver for global enabling and disabling of interrupts. + * + * @{ + */ + +#if defined(__DOXYGEN__) +/** + * \def CONFIG_INTERRUPT_FORCE_INTC + * \brief Force usage of the ASF INTC driver + * + * Predefine this symbol when preprocessing to force the use of the ASF INTC driver. + * This is useful to ensure compatibilty accross compilers and shall be used only when required + * by the application needs. + */ +# define CONFIG_INTERRUPT_FORCE_INTC +#endif + +//! \name Global interrupt flags +//@{ +/** + * \typedef irqflags_t + * \brief Type used for holding state of interrupt flag + */ + +/** + * \def cpu_irq_enable + * \brief Enable interrupts globally + */ + +/** + * \def cpu_irq_disable + * \brief Disable interrupts globally + */ + +/** + * \fn irqflags_t cpu_irq_save(void) + * \brief Get and clear the global interrupt flags + * + * Use in conjunction with \ref cpu_irq_restore. + * + * \return Current state of interrupt flags. + * + * \note This function leaves interrupts disabled. + */ + +/** + * \fn void cpu_irq_restore(irqflags_t flags) + * \brief Restore global interrupt flags + * + * Use in conjunction with \ref cpu_irq_save. + * + * \param flags State to set interrupt flag to. + */ + +/** + * \fn bool cpu_irq_is_enabled_flags(irqflags_t flags) + * \brief Check if interrupts are globally enabled in supplied flags + * + * \param flags Currents state of interrupt flags. + * + * \return True if interrupts are enabled. + */ + +/** + * \def cpu_irq_is_enabled + * \brief Check if interrupts are globally enabled + * + * \return True if interrupts are enabled. + */ +//@} + +//! @} + +/** + * \ingroup interrupt_group + * \defgroup interrupt_deprecated_group Deprecated interrupt definitions + */ + +#endif /* UTILS_INTERRUPT_H */ diff --git a/DSTAT-temp/src/asf/common/utils/interrupt/interrupt_avr8.h b/DSTAT-temp/src/asf/common/utils/interrupt/interrupt_avr8.h new file mode 100644 index 0000000..3f6f1ff --- /dev/null +++ b/DSTAT-temp/src/asf/common/utils/interrupt/interrupt_avr8.h @@ -0,0 +1,138 @@ +/** + * \file + * + * \brief Global interrupt management for 8-bit AVR + * + * Copyright (c) 2010 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef UTILS_INTERRUPT_INTERRUPT_H +#define UTILS_INTERRUPT_INTERRUPT_H + +#include +#include + +/** + * \weakgroup interrupt_group + * + * @{ + */ + +/** + * \def ISR + * \brief Define service routine for specified interrupt vector + * + * Usage: + * \code + * ISR(FOO_vect) + * { + * ... + * } + * \endcode + * + * \param vect Interrupt vector name as found in the device header files. + */ +#if defined(__DOXYGEN__) +# define ISR(vect) +#elif defined(__GNUC__) +# include +#elif defined(__ICCAVR__) +# define __ISR(x) _Pragma(#x) +# define ISR(vect) __ISR(vector=vect) __interrupt void handler_##vect(void) +#endif + +#if XMEGA +/** + * \brief Initialize interrupt vectors + * Enables all interrupt levels, with vectors located in the application section + * and fixed priority scheduling. + */ +#define irq_initialize_vectors() \ + PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; +#endif + +#ifdef __GNUC__ +# define cpu_irq_enable() sei() +# define cpu_irq_disable() cli() +#else +# define cpu_irq_enable() __enable_interrupt() +# define cpu_irq_disable() __disable_interrupt() +#endif + +typedef uint8_t irqflags_t; + +static inline irqflags_t cpu_irq_save(void) +{ + irqflags_t flags = SREG; + cpu_irq_disable(); + return flags; +} + +static inline void cpu_irq_restore(irqflags_t flags) +{ + barrier(); + SREG = flags; +} + +static inline bool cpu_irq_is_enabled_flags(irqflags_t flags) +{ +#if XMEGA +# ifdef __GNUC__ + return flags & CPU_I_bm; +# else + return flags & I_bm; +# endif +#elif MEGA + return flags & (1 << SREG_I); +#endif +} + +#define cpu_irq_is_enabled() cpu_irq_is_enabled_flags(SREG) + +//! @} + +/** + * \weakgroup interrupt_deprecated_group + * @{ + */ +// Deprecated definitions. +#define Enable_global_interrupt() cpu_irq_enable() +#define Disable_global_interrupt() cpu_irq_disable() +#define Is_global_interrupt_enabled() cpu_irq_is_enabled() +//! @} + +#endif /* UTILS_INTERRUPT_INTERRUPT_H */ diff --git a/DSTAT-temp/src/asf/common/utils/make/Makefile.avr.in b/DSTAT-temp/src/asf/common/utils/make/Makefile.avr.in new file mode 100644 index 0000000..65a208d --- /dev/null +++ b/DSTAT-temp/src/asf/common/utils/make/Makefile.avr.in @@ -0,0 +1,455 @@ +# List of available make goals: +# +# all Default target, builds the project +# clean Clean up the project +# rebuild Rebuild the project +# +# doc Build the documentation +# cleandoc Clean up the documentation +# rebuilddoc Rebuild the documentation +# +# +# Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. +# +# \asf_license_start +# +# \page License +# +# 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. The name of Atmel may not be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# 4. This software may only be redistributed and used in connection with an +# Atmel microcontroller product. +# +# THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE +# EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. +# +# \asf_license_stop +# + +# Include the config.mk file from the current working path, e.g., where the +# user called make. +include config.mk + +# Tool to use to generate documentation from the source code +DOCGEN ?= doxygen + +# Look for source files relative to the top-level source directory +VPATH := $(PRJ_PATH) + +# Output target file +target := $(TARGET) + +# Output project name (target name minus suffix) +project := $(basename $(target)) + +# Output target file (typically ELF or static library) +ifeq ($(suffix $(target)),.a) +target_type := lib +else +ifeq ($(suffix $(target)),.elf) +target_type := elf +else +$(error "Target type $(target_type) is not supported") +endif +endif + +# Allow override of operating system detection. The user can add OS=Linux or +# OS=Windows on the command line to explicit set the host OS. +# +# This allows to work around broken uname utility on certain systems. +ifdef OS + ifeq ($(strip $(OS)), Linux) + os_type := Linux + endif + ifeq ($(strip $(OS)), Windows) + os_type := windows32_64 + endif +endif + +os_type ?= $(strip $(shell uname)) + +ifeq ($(os_type),windows32) +os := Windows +else +ifeq ($(os_type),windows64) +os := Windows +else +ifeq ($(os_type),windows32_64) +os ?= Windows +else +ifeq ($(os_type),) +os := Windows +else +# Default to Linux style operating system. Both Cygwin and mingw are fully +# compatible (for this Makefile) with Linux. +os := Linux +endif +endif +endif +endif + +# Output documentation directory and configuration file. +docdir := ../doxygen/html +doccfg := ../doxygen/doxyfile.doxygen + +CROSS ?= avr- +AR := $(CROSS)ar +AS := $(CROSS)as +CC := $(CROSS)gcc +CPP := $(CROSS)gcc -E +CXX := $(CROSS)g++ +LD := $(CROSS)g++ +NM := $(CROSS)nm +OBJCOPY := $(CROSS)objcopy +OBJDUMP := $(CROSS)objdump +SIZE := $(CROSS)size + +RM := rm +ifeq ($(os),Windows) +RMDIR := rmdir /S /Q +else +RMDIR := rmdir -p --ignore-fail-on-non-empty +endif + +# Strings for beautifying output +MSG_CLEAN_FILES = "RM *.o *.d" +MSG_CLEAN_DIRS = "RMDIR $(strip $(clean-dirs))" +MSG_CLEAN_DOC = "RMDIR $(docdir)" +MSG_MKDIR = "MKDIR $(dir $@)" + +MSG_INFO = "INFO " + +MSG_ARCHIVING = "AR $@" +MSG_ASSEMBLING = "AS $@" +MSG_BINARY_IMAGE = "OBJCOPY $@" +MSG_COMPILING = "CC $@" +MSG_COMPILING_CXX = "CXX $@" +MSG_EEPROM_IMAGE = "OBJCOPY $@" +MSG_EXTENDED_LISTING = "OBJDUMP $@" +MSG_IHEX_IMAGE = "OBJCOPY $@" +MSG_LINKING = "LN $@" +MSG_PREPROCESSING = "CPP $@" +MSG_SIZE = "SIZE $@" +MSG_SYMBOL_TABLE = "NM $@" + +MSG_GENERATING_DOC = "DOXYGEN $(docdir)" + +# Don't use make's built-in rules and variables +MAKEFLAGS += -rR + +# Don't print 'Entering directory ...' +MAKEFLAGS += --no-print-directory + +# Function for reversing the order of a list +reverse = $(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1)) + +# Hide command output by default, but allow the user to override this +# by adding V=1 on the command line. +# +# This is inspired by the Kbuild system used by the Linux kernel. +ifdef V + ifeq ("$(origin V)", "command line") + VERBOSE = $(V) + endif +endif +ifndef VERBOSE + VERBOSE = 0 +endif + +ifeq ($(VERBOSE), 1) + Q = +else + Q = @ +endif + +arflags-gnu-y := $(ARFLAGS) +asflags-gnu-y := $(ASFLAGS) +cflags-gnu-y := $(CFLAGS) +cxxflags-gnu-y := $(CXXFLAGS) +cppflags-gnu-y := $(CPPFLAGS) +cpuflags-gnu-y := +dbgflags-gnu-y := $(DBGFLAGS) +libflags-gnu-y := $(foreach LIB,$(LIBS),-l$(LIB)) +ldflags-gnu-y := $(LDFLAGS) +flashflags-gnu-y := $(FLASHFLAGS) +eepromflags-gnu-y := $(EEPROMFLAGS) +clean-files := +clean-dirs := + +clean-files += $(wildcard $(target) $(project).map) +clean-files += $(wildcard $(project).hex $(project).eep) +clean-files += $(wildcard $(project).lss $(project).sym) +clean-files += $(wildcard $(build)) + +# Use pipes instead of temporary files for communication between processes +cflags-gnu-y += -pipe +asflags-gnu-y += -pipe +ldflags-gnu-y += -pipe + +# Archiver flags. +arflags-gnu-y += rcs + +# Always enable warnings. And be very careful about implicit +# declarations. +cflags-gnu-y += -Wall -Wstrict-prototypes -Wmissing-prototypes +cflags-gnu-y += -Werror-implicit-function-declaration +cxxflags-gnu-y += -Wall +# IAR doesn't allow arithmetic on void pointers, so warn about that. +cflags-gnu-y += -Wpointer-arith +cxxflags-gnu-y += -Wpointer-arith + +# Preprocessor flags. +cppflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),-I$(INC)) +asflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),'-Wa,-I$(INC)') + +# CPU specific flags. +cpuflags-gnu-y += -mmcu=$(MCU) + +# Dependency file flags. +depflags = -MD -MP -MQ $@ + +# Debug specific flags. +ifdef BUILD_DEBUG_LEVEL +dbgflags-gnu-y += -g$(BUILD_DEBUG_LEVEL) +else +dbgflags-gnu-y += -gdwarf-2 +endif + +# Optimization specific flags. +ifdef BUILD_OPTIMIZATION +optflags-gnu-y = -O$(BUILD_OPTIMIZATION) +else +optflags-gnu-y = $(OPTIMIZATION) +endif + +# Relax compilation and linking. +cflags-gnu-y += -mrelax +cxxflags-gnu-y += -mrelax +asflags-gnu-y += -mrelax +ldflags-gnu-y += -Wl,--relax + +# Always preprocess assembler files. +asflags-gnu-y += -x assembler-with-cpp +# Compile C files using the GNU99 standard. +cflags-gnu-y += -std=gnu99 +# Compile C++ files using the GNU++98 standard. +cxxflags-gnu-y += -std=gnu++98 + +# Use unsigned character type when compiling. +cflags-gnu-y += -funsigned-char +cxxflags-gnu-y += -funsigned-char + +# Separate each function and data into its own separate section to allow +# garbage collection of unused sections. +cflags-gnu-y += -ffunction-sections -fdata-sections +cxxflags-gnu-y += -ffunction-sections -fdata-sections + +# Garbage collect unreferred sections when linking. +ldflags-gnu-y += -Wl,--gc-sections + +# Output a link map file and a cross reference table +ldflags-gnu-y += -Wl,-Map=$(project).map,--cref + +# Add library search paths relative to the top level directory. +ldflags-gnu-y += $(foreach _LIB_PATH,$(addprefix $(PRJ_PATH)/,$(LIB_PATH)),-L$(_LIB_PATH)) + +a_flags = $(cpuflags-gnu-y) $(depflags) $(cppflags-gnu-y) $(asflags-gnu-y) -D__ASSEMBLY__ +c_flags = $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cflags-gnu-y) +cxx_flags= $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cxxflags-gnu-y) +l_flags = $(cpuflags-gnu-y) $(optflags-gnu-y) $(ldflags-gnu-y) +ar_flags = $(arflags-gnu-y) + +# Intel Hex file production flags +flashflags-gnu-y += -R .eeprom -R .usb_descriptor_table + +# Eeprom file production flags +eepromflags-gnu-y += -j .eeprom +eepromflags-gnu-y += --set-section-flags=.eeprom="alloc,load" +eepromflags-gnu-y += --change-section-lma .eeprom=0 + +# Source files list and part informations must already be included before +# running this makefile + +# If a custom build directory is specified, use it -- force trailing / in directory name. +ifdef BUILD_DIR + build-dir := $(dir $(BUILD_DIR))$(if $(notdir $(BUILD_DIR)),$(notdir $(BUILD_DIR))/) +else + build-dir = +endif + +# Create object files list from source files list. +obj-y := $(addprefix $(build-dir), $(addsuffix .o,$(basename $(CSRCS) $(ASSRCS)))) + +# Create dependency files list from source files list. +dep-files := $(wildcard $(foreach f,$(obj-y),$(basename $(f)).d)) + +clean-files += $(wildcard $(obj-y)) +clean-files += $(dep-files) + +clean-dirs += $(call reverse,$(sort $(wildcard $(dir $(obj-y))))) + +# Default target. +.PHONY: all +ifeq ($(target_type),lib) +all: $(target) $(project).lss $(project).sym +else +ifeq ($(target_type),elf) +all: $(target) $(project).hex $(project).lss $(project).sym +endif +endif + +# Clean up the project. +.PHONY: clean +clean: + @$(if $(strip $(clean-files)),echo $(MSG_CLEAN_FILES)) + $(if $(strip $(clean-files)),$(Q)$(RM) $(clean-files),) + @$(if $(strip $(clean-dirs)),echo $(MSG_CLEAN_DIRS)) +# Remove created directories, and make sure we only remove existing +# directories, since recursive rmdir might help us a bit on the way. +ifeq ($(os),Windows) + $(Q)$(if $(strip $(clean-dirs)), \ + $(RMDIR) $(strip $(subst /,\,$(clean-dirs)))) +else + $(Q)$(if $(strip $(clean-dirs)), \ + for directory in $(strip $(clean-dirs)); do \ + if [ -d "$$directory" ]; then \ + $(RMDIR) $$directory; \ + fi \ + done \ + ) +endif + +# Rebuild the project. +.PHONY: rebuild +rebuild: clean all + +.PHONY: objfiles +objfiles: $(obj-y) + +# Create object files from C source files. +$(build-dir)%.o: %.c $(PRJ_PATH)/common/utils/make/Makefile.avr.in config.mk + $(Q)test -d $(dir $@) || echo $(MSG_MKDIR) +ifeq ($(os),Windows) + $(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@)) +else + $(Q)test -d $(dir $@) || mkdir -p $(dir $@) +endif + @echo $(MSG_COMPILING) + $(Q)$(CC) $(c_flags) -c $< -o $@ + +# Create object files from C++ source files. +$(build-dir)%.o: %.cpp $(PRJ_PATH)/common/utils/make/Makefile.avr.in config.mk + $(Q)test -d $(dir $@) || echo $(MSG_MKDIR) +ifeq ($(os),Windows) + $(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@)) +else + $(Q)test -d $(dir $@) || mkdir -p $(dir $@) +endif + @echo $(MSG_COMPILING_CXX) + $(Q)$(CXX) $(cxx_flags) -c $< -o $@ + +# Preprocess and assemble: create object files from assembler source files. +$(build-dir)%.o: %.s $(PRJ_PATH)/common/utils/make/Makefile.avr.in config.mk + $(Q)test -d $(dir $@) || echo $(MSG_MKDIR) +ifeq ($(os),Windows) + $(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@)) +else + $(Q)test -d $(dir $@) || mkdir -p $(dir $@) +endif + @echo $(MSG_ASSEMBLING) + $(Q)$(CC) $(a_flags) -c $< -o $@ + +# Preprocess and assemble: create object files from assembler source files. +$(build-dir)%.o: %.S $(PRJ_PATH)/common/utils/make/Makefile.avr.in config.mk + $(Q)test -d $(dir $@) || echo $(MSG_MKDIR) +ifeq ($(os),Windows) + $(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@)) +else + $(Q)test -d $(dir $@) || mkdir -p $(dir $@) +endif + @echo $(MSG_ASSEMBLING) + $(Q)$(CC) $(a_flags) -c $< -o $@ + +# Include all dependency files to add depedency to all header files in use. +include $(dep-files) + +ifeq ($(target_type),lib) +# Archive object files into an archive +$(target): $(PRJ_PATH)/common/utils/make/Makefile.avr.in config.mk $(obj-y) + @echo $(MSG_ARCHIVING) + $(Q)$(AR) $(ar_flags) $@ $(obj-y) + @echo $(MSG_SIZE) + $(Q)$(SIZE) -Bxt $@ +else +ifeq ($(target_type),elf) +# Link the object files into an ELF file. Also make sure the target is rebuilt +# if the common Makefile.avr.in or project config.mk is changed. +$(target): $(PRJ_PATH)/common/utils/make/Makefile.avr.in config.mk $(obj-y) + @echo $(MSG_LINKING) + $(Q)$(CC) $(l_flags) $(obj-y) $(libflags-gnu-y) -o $@ + @echo $(MSG_SIZE) + $(Q)$(SIZE) -Ax $@ + $(Q)$(SIZE) -Bx $@ +endif +endif + +# Create extended function listing from target output file. +%.lss: $(target) + @echo $(MSG_EXTENDED_LISTING) + $(Q)$(OBJDUMP) -h -S $< > $@ + +# Create symbol table from target output file. +%.sym: $(target) + @echo $(MSG_SYMBOL_TABLE) + $(Q)$(NM) -n $< > $@ + +# Create Intel HEX image from ELF output file. +%.hex: $(target) + @echo $(MSG_IHEX_IMAGE) + $(Q)$(OBJCOPY) -O ihex $(flashflags-gnu-y) $< $@ + +# Create EEPROM Intel HEX image from ELF output file. +%.eep: $(target) + @echo $(MSG_EEPROM_IMAGE) + $(Q)$(OBJCOPY) $(eepromflags-gnu-y) -O ihex $< $@ || exit 0 + +# Provide information about the detected host operating system. +.SECONDARY: info-os +info-os: + @echo $(MSG_INFO)$(os) build host detected + +# Build Doxygen generated documentation. +.PHONY: doc +doc: + @echo $(MSG_GENERATING_DOC) + $(Q)cd $(dir $(doccfg)) && $(DOCGEN) $(notdir $(doccfg)) + +# Clean Doxygen generated documentation. +.PHONY: cleandoc +cleandoc: + @$(if $(wildcard $(docdir)),echo $(MSG_CLEAN_DOC)) + $(Q)$(if $(wildcard $(docdir)),$(RM) --recursive $(docdir)) + +# Rebuild the Doxygen generated documentation. +.PHONY: rebuilddoc +rebuilddoc: cleandoc doc diff --git a/DSTAT-temp/src/asf/common/utils/parts.h b/DSTAT-temp/src/asf/common/utils/parts.h new file mode 100644 index 0000000..532e36b --- /dev/null +++ b/DSTAT-temp/src/asf/common/utils/parts.h @@ -0,0 +1,671 @@ +/** + * \file + * + * \brief Atmel part identification macros + * + * Copyright (C) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef ATMEL_PARTS_H +#define ATMEL_PARTS_H + +/** + * \defgroup part_macros_group Atmel part identification macros + * + * This collection of macros identify which series and families that the various + * Atmel parts belong to. These can be used to select part-dependent sections of + * code at compile time. + * + * @{ + */ + +/** + * \name Convenience macros for part checking + * @{ + */ +//! Check GCC and IAR part definition for 8-bit AVR +#define AVR8_PART_IS_DEFINED(part) \ + (defined(__ ## part ## __) || defined(__AVR_ ## part ## __)) + +//! Check GCC and IAR part definition for 32-bit AVR +#define AVR32_PART_IS_DEFINED(part) \ + (defined(__AT32 ## part ## __) || defined(__AVR32_ ## part ## __)) + +//! Check GCC and IAR part definition for SAM +#define SAM_PART_IS_DEFINED(part) (defined(__ ## part ## __)) +/** @} */ + +/** + * \defgroup uc3_part_macros_group AVR UC3 parts + * @{ + */ + +/** + * \name AVR UC3 A series + * @{ + */ +#define UC3A0 ( \ + AVR32_PART_IS_DEFINED(UC3A0128) || \ + AVR32_PART_IS_DEFINED(UC3A0256) || \ + AVR32_PART_IS_DEFINED(UC3A0512) \ + ) + +#define UC3A1 ( \ + AVR32_PART_IS_DEFINED(UC3A1128) || \ + AVR32_PART_IS_DEFINED(UC3A1256) || \ + AVR32_PART_IS_DEFINED(UC3A1512) \ + ) + +#define UC3A3 ( \ + AVR32_PART_IS_DEFINED(UC3A364) || \ + AVR32_PART_IS_DEFINED(UC3A364S) || \ + AVR32_PART_IS_DEFINED(UC3A3128) || \ + AVR32_PART_IS_DEFINED(UC3A3128S) || \ + AVR32_PART_IS_DEFINED(UC3A3256) || \ + AVR32_PART_IS_DEFINED(UC3A3256S) \ + ) + +#define UC3A4 ( \ + AVR32_PART_IS_DEFINED(UC3A464) || \ + AVR32_PART_IS_DEFINED(UC3A464S) || \ + AVR32_PART_IS_DEFINED(UC3A4128) || \ + AVR32_PART_IS_DEFINED(UC3A4128S) || \ + AVR32_PART_IS_DEFINED(UC3A4256) || \ + AVR32_PART_IS_DEFINED(UC3A4256S) \ + ) +/** @} */ + +/** + * \name AVR UC3 B series + * @{ + */ +#define UC3B0 ( \ + AVR32_PART_IS_DEFINED(UC3B064) || \ + AVR32_PART_IS_DEFINED(UC3B0128) || \ + AVR32_PART_IS_DEFINED(UC3B0256) || \ + AVR32_PART_IS_DEFINED(UC3B0512) \ + ) + +#define UC3B1 ( \ + AVR32_PART_IS_DEFINED(UC3B164) || \ + AVR32_PART_IS_DEFINED(UC3B1128) || \ + AVR32_PART_IS_DEFINED(UC3B1256) || \ + AVR32_PART_IS_DEFINED(UC3B1512) \ + ) +/** @} */ + +/** + * \name AVR UC3 C series + * @{ + */ +#define UC3C0 ( \ + AVR32_PART_IS_DEFINED(UC3C064C) || \ + AVR32_PART_IS_DEFINED(UC3C0128C) || \ + AVR32_PART_IS_DEFINED(UC3C0256C) || \ + AVR32_PART_IS_DEFINED(UC3C0512C) \ + ) + +#define UC3C1 ( \ + AVR32_PART_IS_DEFINED(UC3C164C) || \ + AVR32_PART_IS_DEFINED(UC3C1128C) || \ + AVR32_PART_IS_DEFINED(UC3C1256C) || \ + AVR32_PART_IS_DEFINED(UC3C1512C) \ + ) + +#define UC3C2 ( \ + AVR32_PART_IS_DEFINED(UC3C264C) || \ + AVR32_PART_IS_DEFINED(UC3C2128C) || \ + AVR32_PART_IS_DEFINED(UC3C2256C) || \ + AVR32_PART_IS_DEFINED(UC3C2512C) \ + ) +/** @} */ + +/** + * \name AVR UC3 D series + * @{ + */ +#define UC3D3 ( \ + AVR32_PART_IS_DEFINED(UC64D3) || \ + AVR32_PART_IS_DEFINED(UC128D3) \ + ) + +#define UC3D4 ( \ + AVR32_PART_IS_DEFINED(UC64D4) || \ + AVR32_PART_IS_DEFINED(UC128D4) \ + ) +/** @} */ + +/** + * \name AVR UC3 L series + * @{ + */ +#define UC3L0 ( \ + AVR32_PART_IS_DEFINED(UC3L016) || \ + AVR32_PART_IS_DEFINED(UC3L032) || \ + AVR32_PART_IS_DEFINED(UC3L064) \ + ) + +#define UC3L0128 ( \ + AVR32_PART_IS_DEFINED(UC3L0128) \ + ) + +#define UC3L0256 ( \ + AVR32_PART_IS_DEFINED(UC3L0256) \ + ) + +#define UC3L3 ( \ + AVR32_PART_IS_DEFINED(UC64L3U) || \ + AVR32_PART_IS_DEFINED(UC128L3U) || \ + AVR32_PART_IS_DEFINED(UC256L3U) \ + ) + +#define UC3L4 ( \ + AVR32_PART_IS_DEFINED(UC64L4U) || \ + AVR32_PART_IS_DEFINED(UC128L4U) || \ + AVR32_PART_IS_DEFINED(UC256L4U) \ + ) + +#define UC3L3_L4 (UC3L3 || UC3L4) +/** @} */ + +/** + * \name AVR UC3 families + * @{ + */ +/** AVR UC3 A family */ +#define UC3A (UC3A0 || UC3A1 || UC3A3 || UC3A4) + +/** AVR UC3 B family */ +#define UC3B (UC3B0 || UC3B1) + +/** AVR UC3 C family */ +#define UC3C (UC3C0 || UC3C1 || UC3C2) + +/** AVR UC3 D family */ +#define UC3D (UC3D3 || UC3D4) + +/** AVR UC3 L family */ +#define UC3L (UC3L0 || UC3L0128 || UC3L0256 || UC3L3_L4) +/** @} */ + +/** AVR UC3 product line */ +#define UC3 (UC3A || UC3B || UC3C || UC3D || UC3L) + +/** @} */ + +/** + * \defgroup xmega_part_macros_group AVR XMEGA parts + * @{ + */ + +/** + * \name AVR XMEGA A series + * @{ + */ +#define XMEGA_A1 ( \ + AVR8_PART_IS_DEFINED(ATxmega64A1) || \ + AVR8_PART_IS_DEFINED(ATxmega128A1) \ + ) + +#define XMEGA_A3 ( \ + AVR8_PART_IS_DEFINED(ATxmega64A3) || \ + AVR8_PART_IS_DEFINED(ATxmega128A3) || \ + AVR8_PART_IS_DEFINED(ATxmega192A3) || \ + AVR8_PART_IS_DEFINED(ATxmega256A3) \ + ) + +#define XMEGA_A3B ( \ + AVR8_PART_IS_DEFINED(ATxmega256A3B) \ + ) + +#define XMEGA_A4 ( \ + AVR8_PART_IS_DEFINED(ATxmega16A4) || \ + AVR8_PART_IS_DEFINED(ATxmega32A4) \ + ) +/** @} */ + +/** + * \name AVR XMEGA AU series + * @{ + */ +#define XMEGA_A1U ( \ + AVR8_PART_IS_DEFINED(ATxmega64A1U) || \ + AVR8_PART_IS_DEFINED(ATxmega128A1U) \ + ) + +#define XMEGA_A3U ( \ + AVR8_PART_IS_DEFINED(ATxmega64A3U) || \ + AVR8_PART_IS_DEFINED(ATxmega128A3U) || \ + AVR8_PART_IS_DEFINED(ATxmega192A3U) || \ + AVR8_PART_IS_DEFINED(ATxmega256A3U) \ + ) + +#define XMEGA_A3BU ( \ + AVR8_PART_IS_DEFINED(ATxmega256A3BU) \ + ) + +#define XMEGA_A4U ( \ + AVR8_PART_IS_DEFINED(ATxmega16A4U) || \ + AVR8_PART_IS_DEFINED(ATxmega32A4U) || \ + AVR8_PART_IS_DEFINED(ATxmega64A4U) || \ + AVR8_PART_IS_DEFINED(ATxmega128A4U) \ + ) +/** @} */ + +/** + * \name AVR XMEGA B series + * @{ + */ +#define XMEGA_B1 ( \ + AVR8_PART_IS_DEFINED(ATxmega64B1) || \ + AVR8_PART_IS_DEFINED(ATxmega128B1) \ + ) + +#define XMEGA_B3 ( \ + AVR8_PART_IS_DEFINED(ATxmega64B3) || \ + AVR8_PART_IS_DEFINED(ATxmega128B3) \ + ) +/** @} */ + +/** + * \name AVR XMEGA C series + * @{ + */ +#define XMEGA_C3 ( \ + AVR8_PART_IS_DEFINED(ATxmega384C3) || \ + AVR8_PART_IS_DEFINED(ATxmega256C3) || \ + AVR8_PART_IS_DEFINED(ATxmega128C3) || \ + AVR8_PART_IS_DEFINED(ATxmega64C3) \ + ) + +#define XMEGA_C4 ( \ + AVR8_PART_IS_DEFINED(ATxmega32C4) || \ + AVR8_PART_IS_DEFINED(ATxmega16C4) \ + ) +/** @} */ + +/** + * \name AVR XMEGA D series + * @{ + */ +#define XMEGA_D3 ( \ + AVR8_PART_IS_DEFINED(ATxmega64D3) || \ + AVR8_PART_IS_DEFINED(ATxmega128D3) || \ + AVR8_PART_IS_DEFINED(ATxmega192D3) || \ + AVR8_PART_IS_DEFINED(ATxmega256D3) || \ + AVR8_PART_IS_DEFINED(ATxmega384D3) \ + ) + +#define XMEGA_D4 ( \ + AVR8_PART_IS_DEFINED(ATxmega16D4) || \ + AVR8_PART_IS_DEFINED(ATxmega32D4) || \ + AVR8_PART_IS_DEFINED(ATxmega64D4) || \ + AVR8_PART_IS_DEFINED(ATxmega128D4) \ + ) +/** @} */ + +/** + * \name AVR XMEGA families + * @{ + */ +/** AVR XMEGA A family */ +#define XMEGA_A (XMEGA_A1 || XMEGA_A3 || XMEGA_A3B || XMEGA_A4) + +/** AVR XMEGA AU family */ +#define XMEGA_AU (XMEGA_A1U || XMEGA_A3U || XMEGA_A3BU || XMEGA_A4U) + +/** AVR XMEGA B family */ +#define XMEGA_B (XMEGA_B1 || XMEGA_B3) + +/** AVR XMEGA C family */ +#define XMEGA_C (XMEGA_C3 || XMEGA_C4) + +/** AVR XMEGA D family */ +#define XMEGA_D (XMEGA_D3 || XMEGA_D4) +/** @} */ + +/** AVR XMEGA product line */ +#define XMEGA (XMEGA_A || XMEGA_AU || XMEGA_B || XMEGA_C || XMEGA_D) + +/** @} */ + +/** + * \defgroup mega_part_macros_group megaAVR parts + * + * \note These megaAVR groupings are based on the groups in AVR Libc for the + * part header files. They are not names of official megaAVR device series or + * families. + * + * @{ + */ + +/** + * \name ATmegaxx0/xx1 subgroups + * @{ + */ +#define MEGA_XX0 ( \ + AVR8_PART_IS_DEFINED(ATmega640) || \ + AVR8_PART_IS_DEFINED(ATmega1280) || \ + AVR8_PART_IS_DEFINED(ATmega2560) \ + ) + +#define MEGA_XX1 ( \ + AVR8_PART_IS_DEFINED(ATmega1281) || \ + AVR8_PART_IS_DEFINED(ATmega2561) \ + ) +/** @} */ + +/** + * \name megaAVR groups + * @{ + */ +/** ATmegaxx0/xx1 group */ +#define MEGA_XX0_1 (MEGA_XX0 || MEGA_XX1) + +/** ATmegaxx4 group */ +#define MEGA_XX4 ( \ + AVR8_PART_IS_DEFINED(ATmega164A) || \ + AVR8_PART_IS_DEFINED(ATmega164PA) || \ + AVR8_PART_IS_DEFINED(ATmega324) || \ + AVR8_PART_IS_DEFINED(ATmega324A) || \ + AVR8_PART_IS_DEFINED(ATmega324PA) || \ + AVR8_PART_IS_DEFINED(ATmega644) || \ + AVR8_PART_IS_DEFINED(ATmega644A) || \ + AVR8_PART_IS_DEFINED(ATmega644PA) || \ + AVR8_PART_IS_DEFINED(ATmega1284P) || \ + AVR8_PART_IS_DEFINED(ATmega128RFA1) \ + ) + +/** ATmegaxx4 group */ +#define MEGA_XX4_A ( \ + AVR8_PART_IS_DEFINED(ATmega164A) || \ + AVR8_PART_IS_DEFINED(ATmega164PA) || \ + AVR8_PART_IS_DEFINED(ATmega324A) || \ + AVR8_PART_IS_DEFINED(ATmega324PA) || \ + AVR8_PART_IS_DEFINED(ATmega644A) || \ + AVR8_PART_IS_DEFINED(ATmega644PA) || \ + AVR8_PART_IS_DEFINED(ATmega1284P) \ + ) + +/** ATmegaxx8 group */ +#define MEGA_XX8 ( \ + AVR8_PART_IS_DEFINED(ATmega48) || \ + AVR8_PART_IS_DEFINED(ATmega48A) || \ + AVR8_PART_IS_DEFINED(ATmega48PA) || \ + AVR8_PART_IS_DEFINED(ATmega88) || \ + AVR8_PART_IS_DEFINED(ATmega88A) || \ + AVR8_PART_IS_DEFINED(ATmega88PA) || \ + AVR8_PART_IS_DEFINED(ATmega168) || \ + AVR8_PART_IS_DEFINED(ATmega168A) || \ + AVR8_PART_IS_DEFINED(ATmega168PA) || \ + AVR8_PART_IS_DEFINED(ATmega328) || \ + AVR8_PART_IS_DEFINED(ATmega328P) \ + ) + +/** ATmegaxx8A/P/PA group */ +#define MEGA_XX8_A ( \ + AVR8_PART_IS_DEFINED(ATmega48A) || \ + AVR8_PART_IS_DEFINED(ATmega48PA) || \ + AVR8_PART_IS_DEFINED(ATmega88A) || \ + AVR8_PART_IS_DEFINED(ATmega88PA) || \ + AVR8_PART_IS_DEFINED(ATmega168A) || \ + AVR8_PART_IS_DEFINED(ATmega168PA) || \ + AVR8_PART_IS_DEFINED(ATmega328P) \ + ) + +/** ATmegaxx group */ +#define MEGA_XX ( \ + AVR8_PART_IS_DEFINED(ATmega16) || \ + AVR8_PART_IS_DEFINED(ATmega16A) || \ + AVR8_PART_IS_DEFINED(ATmega32) || \ + AVR8_PART_IS_DEFINED(ATmega32A) || \ + AVR8_PART_IS_DEFINED(ATmega64) || \ + AVR8_PART_IS_DEFINED(ATmega64A) || \ + AVR8_PART_IS_DEFINED(ATmega128) || \ + AVR8_PART_IS_DEFINED(ATmega128A) \ + ) + +/** ATmegaxxA/P/PA group */ +#define MEGA_XX_A ( \ + AVR8_PART_IS_DEFINED(ATmega16A) || \ + AVR8_PART_IS_DEFINED(ATmega32A) || \ + AVR8_PART_IS_DEFINED(ATmega64A) || \ + AVR8_PART_IS_DEFINED(ATmega128A) \ + ) + +/** Unspecified group */ +#define MEGA_UNSPECIFIED ( \ + AVR8_PART_IS_DEFINED(ATmega16) || \ + AVR8_PART_IS_DEFINED(ATmega16A) || \ + AVR8_PART_IS_DEFINED(ATmega32) || \ + AVR8_PART_IS_DEFINED(ATmega32A) || \ + AVR8_PART_IS_DEFINED(ATmega64) || \ + AVR8_PART_IS_DEFINED(ATmega64A) || \ + AVR8_PART_IS_DEFINED(ATmega128) || \ + AVR8_PART_IS_DEFINED(ATmega128A) || \ + AVR8_PART_IS_DEFINED(ATmega169P) || \ + AVR8_PART_IS_DEFINED(ATmega169PA) || \ + AVR8_PART_IS_DEFINED(ATmega329P) || \ + AVR8_PART_IS_DEFINED(ATmega329PA) \ + ) +/** @} */ + +/** megaAVR product line */ +#define MEGA (MEGA_XX0_1 || MEGA_XX4 || MEGA_XX8 || MEGA_XX || MEGA_UNSPECIFIED) + +/** @} */ + +/** + * \defgroup sam_part_macros_group SAM parts + * @{ + */ + +/** + * \name SAM3S series + * @{ + */ +#define SAM3S1 ( \ + SAM_PART_IS_DEFINED(SAM3S1A) || \ + SAM_PART_IS_DEFINED(SAM3S1B) || \ + SAM_PART_IS_DEFINED(SAM3S1C) \ + ) + +#define SAM3S2 ( \ + SAM_PART_IS_DEFINED(SAM3S2A) || \ + SAM_PART_IS_DEFINED(SAM3S2B) || \ + SAM_PART_IS_DEFINED(SAM3S2C) \ + ) + +#define SAM3S4 ( \ + SAM_PART_IS_DEFINED(SAM3S4A) || \ + SAM_PART_IS_DEFINED(SAM3S4B) || \ + SAM_PART_IS_DEFINED(SAM3S4C) \ + ) + +#define SAM3S8 ( \ + SAM_PART_IS_DEFINED(SAM3S8B) || \ + SAM_PART_IS_DEFINED(SAM3S8C) \ + ) + +#define SAM3SD8 ( \ + SAM_PART_IS_DEFINED(SAM3SD8B) || \ + SAM_PART_IS_DEFINED(SAM3SD8C) \ + ) +/** @} */ + +/** + * \name SAM3U series + * @{ + */ +#define SAM3U1 ( \ + SAM_PART_IS_DEFINED(SAM3U1C) || \ + SAM_PART_IS_DEFINED(SAM3U1E) \ + ) + +#define SAM3U2 ( \ + SAM_PART_IS_DEFINED(SAM3U2C) || \ + SAM_PART_IS_DEFINED(SAM3U2E) \ + ) + +#define SAM3U4 ( \ + SAM_PART_IS_DEFINED(SAM3U4C) || \ + SAM_PART_IS_DEFINED(SAM3U4E) \ + ) +/** @} */ + +/** + * \name SAM3N series + * @{ + */ +#define SAM3N1 ( \ + SAM_PART_IS_DEFINED(SAM3N1A) || \ + SAM_PART_IS_DEFINED(SAM3N1B) || \ + SAM_PART_IS_DEFINED(SAM3N1C) \ + ) + +#define SAM3N2 ( \ + SAM_PART_IS_DEFINED(SAM3N2A) || \ + SAM_PART_IS_DEFINED(SAM3N2B) || \ + SAM_PART_IS_DEFINED(SAM3N2C) \ + ) + +#define SAM3N4 ( \ + SAM_PART_IS_DEFINED(SAM3N4A) || \ + SAM_PART_IS_DEFINED(SAM3N4B) || \ + SAM_PART_IS_DEFINED(SAM3N4C) \ + ) +/** @} */ + +/** + * \name SAM3X series + * @{ + */ +#define SAM3X4 ( \ + SAM_PART_IS_DEFINED(SAM3X4C) || \ + SAM_PART_IS_DEFINED(SAM3X4E) \ + ) + +#define SAM3X8 ( \ + SAM_PART_IS_DEFINED(SAM3X8C) || \ + SAM_PART_IS_DEFINED(SAM3X8E) || \ + SAM_PART_IS_DEFINED(SAM3X8H) \ + ) +/** @} */ + +/** + * \name SAM3A series + * @{ + */ +#define SAM3A4 ( \ + SAM_PART_IS_DEFINED(SAM3A4C) \ + ) + +#define SAM3A8 ( \ + SAM_PART_IS_DEFINED(SAM3A8C) \ + ) +/** @} */ + +/** + * \name SAM4S series + * @{ + */ +#define SAM4S8 ( \ + SAM_PART_IS_DEFINED(SAM4S8B) || \ + SAM_PART_IS_DEFINED(SAM4S8C) \ + ) + +#define SAM4S16 ( \ + SAM_PART_IS_DEFINED(SAM4S16B) || \ + SAM_PART_IS_DEFINED(SAM4S16C) \ + ) +/** @} */ + +/** + * \name SAM4L series + * @{ + */ +#define SAM4LS ( \ + SAM_PART_IS_DEFINED(ATSAM4LS2A) || \ + SAM_PART_IS_DEFINED(ATSAM4LS2B) || \ + SAM_PART_IS_DEFINED(ATSAM4LS2C) || \ + SAM_PART_IS_DEFINED(ATSAM4LS4A) || \ + SAM_PART_IS_DEFINED(ATSAM4LS4B) || \ + SAM_PART_IS_DEFINED(ATSAM4LS4C) \ + ) + +#define SAM4LC ( \ + SAM_PART_IS_DEFINED(ATSAM4LC2A) || \ + SAM_PART_IS_DEFINED(ATSAM4LC2B) || \ + SAM_PART_IS_DEFINED(ATSAM4LC2C) || \ + SAM_PART_IS_DEFINED(ATSAM4LC4A) || \ + SAM_PART_IS_DEFINED(ATSAM4LC4B) || \ + SAM_PART_IS_DEFINED(ATSAM4LC4C) \ + ) +/** @} */ + +/** + * \name SAM families + * @{ + */ +/** SAM3S Family */ +#define SAM3S (SAM3S1 || SAM3S2 || SAM3S4 || SAM3S8 || SAM3SD8) + +/** SAM3U Family */ +#define SAM3U (SAM3U1 || SAM3U2 || SAM3U4) + +/** SAM3N Family */ +#define SAM3N (SAM3N1 || SAM3N2 || SAM3N4) + +/** SAM3XA Family */ +#define SAM3XA (SAM3X4 || SAM3X8 || SAM3A4 || SAM3A8) + +/** SAM4S Family */ +#define SAM4S (SAM4S8 || SAM4S16) + +/** SAM4L Family */ +#define SAM4L (SAM4LS || SAM4LC) +/** @} */ + +/** SAM product line */ +#define SAM (SAM3S || SAM3U || SAM3N || SAM3XA || SAM4S || SAM4L) + +/** @} */ + +/** @} */ + +#endif /* ATMEL_PARTS_H */ diff --git a/DSTAT-temp/src/asf/common/utils/stdio/read.c b/DSTAT-temp/src/asf/common/utils/stdio/read.c new file mode 100644 index 0000000..367c23e --- /dev/null +++ b/DSTAT-temp/src/asf/common/utils/stdio/read.c @@ -0,0 +1,164 @@ +/** + * \file + * + * \brief System-specific implementation of the \ref _read function used by + * the standard library. + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#include "compiler.h" + +/** + * \defgroup group_common_utils_stdio Standard I/O (stdio) + * + * Common standard I/O driver that implements the stdio + * read and write functions on AVR and SAM devices. + * + * \{ + */ + +extern volatile void *volatile stdio_base; +void (*ptr_get)(void volatile*, char*); + + +// IAR common implementation +#if ( defined(__ICCAVR32__) || defined(__ICCAVR__) || defined(__ICCARM__) ) + +#include + +_STD_BEGIN + +#pragma module_name = "?__read" + +/*! \brief Reads a number of bytes, at most \a size, into the memory area + * pointed to by \a buffer. + * + * \param handle File handle to read from. + * \param buffer Pointer to buffer to write read bytes to. + * \param size Number of bytes to read. + * + * \return The number of bytes read, \c 0 at the end of the file, or + * \c _LLIO_ERROR on failure. + */ +size_t __read(int handle, unsigned char *buffer, size_t size) +{ + int nChars = 0; + // This implementation only reads from stdin. + // For all other file handles, it returns failure. + if (handle != _LLIO_STDIN) { + return _LLIO_ERROR; + } + for (; size > 0; --size) { + ptr_get(stdio_base, (char*)buffer); + buffer++; + nChars++; + } + return nChars; +} + +/*! \brief This routine is required by IAR DLIB library since EWAVR V6.10 + * the implementation is empty to be compatible with old IAR version. + */ +int __close(int handle) +{ + UNUSED(handle); + return 0; +} + +/*! \brief This routine is required by IAR DLIB library since EWAVR V6.10 + * the implementation is empty to be compatible with old IAR version. + */ +int remove(const char* val) +{ + UNUSED(val); + return 0; +} + +/*! \brief This routine is required by IAR DLIB library since EWAVR V6.10 + * the implementation is empty to be compatible with old IAR version. + */ +long __lseek(int handle, long val, int val2) +{ + UNUSED(handle); + UNUSED(val2); + return val; +} + +_STD_END + +// GCC AVR32 and SAM implementation +#elif (defined(__GNUC__) && !XMEGA) + +int __attribute__((weak)) +_read (int file, char * ptr, int len); // Remove GCC compiler warning + +int __attribute__((weak)) +_read (int file, char * ptr, int len) +{ + int nChars = 0; + + if (file != 0) { + return -1; + } + + for (; len > 0; --len) { + ptr_get(stdio_base, ptr); + ptr++; + nChars++; + } + return nChars; +} + +// GCC AVR implementation +#elif (defined(__GNUC__) && XMEGA) + +int _read (int *f); // Remove GCC compiler warning + +int _read (int *f) +{ + char c; + ptr_get(stdio_base,&c); + return c; +} +#endif + +/** + * \} + */ + diff --git a/DSTAT-temp/src/asf/common/utils/stdio/stdio_usb/stdio_usb.c b/DSTAT-temp/src/asf/common/utils/stdio/stdio_usb/stdio_usb.c new file mode 100644 index 0000000..9723a94 --- /dev/null +++ b/DSTAT-temp/src/asf/common/utils/stdio/stdio_usb/stdio_usb.c @@ -0,0 +1,133 @@ +/** + * \file + * + * \brief USB CDC Standard I/O Serial Management. + * + * This module defines support routines for a stdio serial interface to the + * Atmel Software Framework (ASF) common USB CDC service. + * + * Copyright (c) 2011 - 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + + +#include "stdio_usb.h" + +static bool stdio_usb_interface_enable = false; + +int stdio_usb_putchar (volatile void * unused, char data) +{ + /* A negative return value should be used to indicate that data + * was not written, but this doesn't seem to work with GCC libc. + */ + if (!stdio_usb_interface_enable) { + return 0; // -1 + } + + return udi_cdc_putc(data) ? 0 : -1; +} + +void stdio_usb_getchar (void volatile * unused, char *data) +{ + /* A negative return value should be used to indicate that data + * was not read, but this doesn't seem to work with GCC libc. + */ + if (!stdio_usb_interface_enable) { + *data = 0; // -1 + return; + } + + *data = (char)udi_cdc_getc(); +} + +void stdio_usb_vbus_event(bool b_high) +{ + if (b_high) { + // Attach USB Device + udc_attach(); + } else { + // VBUS not present + udc_detach(); + } +} + +bool stdio_usb_enable(void) +{ + stdio_usb_interface_enable = true; + return true; +} + +void stdio_usb_disable(void) +{ + stdio_usb_interface_enable = false; +} + +void stdio_usb_init(void) +{ + stdio_base = NULL; + ptr_put = stdio_usb_putchar; + ptr_get = stdio_usb_getchar; + + /* + * Start and attach USB CDC device interface for devices with + * integrated USB interfaces. Assume the VBUS is present if + * VBUS monitoring is not available. + */ + udc_start (); + + if (!udc_include_vbus_monitoring()) { + stdio_usb_vbus_event(true); + } + +#if defined(__GNUC__) +# if XMEGA + // For AVR GCC libc print redirection uses fdevopen. + fdevopen((int (*)(char, FILE*))(_write),(int (*)(FILE*))(_read)); +# endif +# if UC3 || SAM + // For AVR32 and SAM GCC + // Specify that stdout and stdin should not be buffered. + setbuf(stdout, NULL); + setbuf(stdin, NULL); + // Note: Already the case in IAR's Normal DLIB default configuration + // and AVR GCC library: + // - printf() emits one character at a time. + // - getchar() requests only 1 byte to exit. +# endif +#endif +} + diff --git a/DSTAT-temp/src/asf/common/utils/stdio/stdio_usb/stdio_usb.h b/DSTAT-temp/src/asf/common/utils/stdio/stdio_usb/stdio_usb.h new file mode 100644 index 0000000..d61a477 --- /dev/null +++ b/DSTAT-temp/src/asf/common/utils/stdio/stdio_usb/stdio_usb.h @@ -0,0 +1,128 @@ +/** + * \file + * + * \brief USB Standard I/O Serial Management. + * + * This file defines a useful set of functions for the Stdio Serial + * interface on AVR devices. + * + * Copyright (c) 2011 - 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _stdio_usb_h_ +#define _stdio_usb_h_ + +/** + * \defgroup group_common_utils_stdio_stdio_usb USB/CDC Standard I/O (stdio) + * \ingroup group_common_utils_stdio + * + * Standard I/O (stdio) management component that implements a stdio + * USB CDC interface on AVR devices. + * + * \{ + */ + +#include + +#include + +#include +#include + +extern int _write (char c, int *f); +extern int _read (int *f); + + +//! Pointer to the base of the USART module instance to use for stdio. +extern volatile void *volatile stdio_base; +//! Pointer to the external low level write function. +extern int (*ptr_put)(void volatile*, char); +//! Pointer to the external low level read function. +extern void (*ptr_get)(void volatile*, char*); + +/*! \brief Sends a character with the USART. + * + * \param usart Base address of the USART instance. + * \param data Character to write. + * + * \return Status. + * \retval 0 The character was written. + * \retval -1 The function timed out before the transmitter became ready. + */ +int stdio_usb_putchar (volatile void * usart, char data); + +/*! \brief Waits until a character is received, and returns it. + * + * \param usart Base address of the USART instance. + * \param data Data to read + * + * \return Nothing. + */ +void stdio_usb_getchar (void volatile * usart, char * data); + +/*! \brief Callback for VBUS level change event. + * + * \param b_high 1 if VBus is present + * + * \return Nothing. + */ +void stdio_usb_vbus_event (bool b_high); + +/*! \brief Enables the stdio in USB Serial Mode. + * + * \return \c 1 if function was successfully done, otherwise \c 0. + */ +bool stdio_usb_enable(void); + +/*! \brief Disables the stdio in USB Serial Mode. + * + * \return Nothing. + */ +void stdio_usb_disable(void); + +/*! \brief Initializes the stdio in USB Serial Mode. + * + * \return Nothing. + */ +void stdio_usb_init(void); + +/** + * \} + */ + +#endif // _stdio_usb_h_ diff --git a/DSTAT-temp/src/asf/common/utils/stdio/write.c b/DSTAT-temp/src/asf/common/utils/stdio/write.c new file mode 100644 index 0000000..97a65c0 --- /dev/null +++ b/DSTAT-temp/src/asf/common/utils/stdio/write.c @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief System-specific implementation of the \ref _write function used by + * the standard library. + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#include "compiler.h" + +/** + * \addtogroup group_common_utils_stdio + * + * \{ + */ + +volatile void *volatile stdio_base; +int (*ptr_put)(void volatile*, char); + + +#if ( defined(__ICCAVR32__) || defined(__ICCAVR__) || defined(__ICCARM__)) + +#include + +_STD_BEGIN + +#pragma module_name = "?__write" + +/*! \brief Writes a number of bytes, at most \a size, from the memory area + * pointed to by \a buffer. + * + * If \a buffer is zero then \ref __write performs flushing of internal buffers, + * if any. In this case, \a handle can be \c -1 to indicate that all handles + * should be flushed. + * + * \param handle File handle to write to. + * \param buffer Pointer to buffer to read bytes to write from. + * \param size Number of bytes to write. + * + * \return The number of bytes written, or \c _LLIO_ERROR on failure. + */ +size_t __write(int handle, const unsigned char *buffer, size_t size) +{ + size_t nChars = 0; + + if (buffer == 0) { + // This means that we should flush internal buffers. + return 0; + } + + // This implementation only writes to stdout and stderr. + // For all other file handles, it returns failure. + if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) { + return _LLIO_ERROR; + } + + for (; size != 0; --size) { + if (ptr_put(stdio_base, *buffer++) < 0) { + return _LLIO_ERROR; + } + ++nChars; + } + return nChars; +} + +_STD_END + + +#elif (defined(__GNUC__) && !XMEGA) + +int _write (int file, char * ptr, int len); // Remove GCC compiler warning + +int __attribute__((weak)) +_write (int file, char * ptr, int len); + +int __attribute__((weak)) +_write (int file, char * ptr, int len) +{ + int nChars = 0; + + if ((file != 1) && (file != 2) && (file!=3)) { + return -1; + } + + for (; len != 0; --len) { + if (ptr_put(stdio_base, *ptr++) < 0) { + return -1; + } + ++nChars; + } + return nChars; +} + +#elif (defined(__GNUC__) && XMEGA) + +int _write (char c, int *f); + +int _write (char c, int *f) +{ + if (ptr_put(stdio_base, c) < 0) { + return -1; + } + return 1; +} +#endif + +/** + * \} + */ + diff --git a/DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.h b/DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.h new file mode 100644 index 0000000..71d6567 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.h @@ -0,0 +1,120 @@ +/** + * \file + * + * \brief Configuration Change Protection write functions + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef CPU_CCP_H +#define CPU_CCP_H +#include + +/** + * \defgroup ccp_group Configuration Change Protection + * + * See \ref xmega_ccp_quickstart. + * + * Function for writing to protected IO registers. + * @{ + */ + +#if defined(__DOXYGEN__) +//! \name IAR Memory Model defines. +//@{ + +/** + * \def CONFIG_MEMORY_MODEL_TINY + * \brief Configuration symbol to enable 8 bit pointers. + * + */ +# define CONFIG_MEMORY_MODEL_TINY + +/** + * \def CONFIG_MEMORY_MODEL_SMALL + * \brief Configuration symbol to enable 16 bit pointers. + * \note If no memory model is defined, SMALL is default. + * + */ +# define CONFIG_MEMORY_MODEL_SMALL + + +/** + * \def CONFIG_MEMORY_MODEL_LARGE + * \brief Configuration symbol to enable 24 bit pointers. + * + */ +# define CONFIG_MEMORY_MODEL_LARGE + +//@} +#endif + + +/** + * \brief Write to a CCP-protected 8-bit I/O register + * + * \param addr Address of the I/O register + * \param value Value to be written + * + * \note Using IAR Embedded workbench, the choice of memory model has an impact + * on calling convention. The memory model is not visible to the + * preprocessor, so it must be defined in the Assembler preprocessor directives. + */ +extern void ccp_write_io(void *addr, uint8_t value); + +/** @} */ + +/** + * \page xmega_ccp_quickstart Quick start guide for CCP driver + * + * This is the quick start guide for the \ref ccp_group + * "Configuration Change Protection (CCP) driver", with step-by-step + * instructions on how to use the driver. + * + * The use case contains a code fragment, and this can be copied into, e.g., + * the main application function. + * + * \section ccp_basic_use_case Basic use case + * In this use case, the CCP is used to write to the protected XMEGA Clock + * Control register. + * + * \subsection ccp_basic_use_case_setup_flow Workflow + * -# call CCP write io to change system clock selection: + * - \code ccp_write_io((uint8_t *)&CLK.CTRL, CLK_SCLKSEL_RC32M_gc); \endcode + */ + +#endif /* CPU_CCP_H */ diff --git a/DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.s b/DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.s new file mode 100644 index 0000000..91f8fb0 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/cpu/ccp.s @@ -0,0 +1,100 @@ +/** + * \file + * + * \brief Configuration Change Protection + * + * Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include + +//! Value to write to CCP for access to protected IO registers. +#define CCP_IOREG 0xd8 + + /* + * GNU and IAR use different calling conventions. Since this is + * a very small and simple function to begin with, it's easier + * to implement it twice than to deal with the differences + * within a single implementation. + * + * Interrupts are disabled by hardware during the timed + * sequence, so there's no need to save/restore interrupt state. + */ + + PUBLIC_FUNCTION(ccp_write_io) + +#if defined(__GNUC__) + + out RAMPZ, r1 // Reset bits 23:16 of Z + movw r30, r24 // Load addr into Z + ldi r18, CCP_IOREG // Load magic CCP value + out CCP, r18 // Start CCP handshake + st Z, r22 // Write value to I/O register + ret // Return to caller + +#elif defined(__IAR_SYSTEMS_ASM__) + +# if !defined(CONFIG_MEMORY_MODEL_TINY) && !defined(CONFIG_MEMORY_MODEL_SMALL) \ + && !defined(CONFIG_MEMORY_MODEL_LARGE) +# define CONFIG_MEMORY_MODEL_SMALL +# endif + ldi r20, 0 + out RAMPZ, r20 // Reset bits 23:16 of Z +# if defined(CONFIG_MEMORY_MODEL_TINY) + mov r31, r20 // Reset bits 8:15 of Z + mov r30, r16 // Load addr into Z +# else + movw r30, r16 // Load addr into Z +# endif + ldi r21, CCP_IOREG // Load magic CCP value + out CCP, r21 // Start CCP handshake +# if defined(CONFIG_MEMORY_MODEL_TINY) + st Z, r17 // Write value to I/O register +# elif defined(CONFIG_MEMORY_MODEL_SMALL) + st Z, r18 // Write value to I/O register +# elif defined(CONFIG_MEMORY_MODEL_LARGE) + st Z, r19 // Write value to I/O register +# else +# error Unknown memory model in use, no idea how registers should be accessed +# endif + ret +#else +# error Unknown assembler +#endif + + END_FUNC(ccp_write_io) + END_FILE() diff --git a/DSTAT-temp/src/asf/xmega/drivers/cpu/xmega_reset_cause.h b/DSTAT-temp/src/asf/xmega/drivers/cpu/xmega_reset_cause.h new file mode 100644 index 0000000..0b5cc45 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/cpu/xmega_reset_cause.h @@ -0,0 +1,105 @@ +/** + * \file + * + * \brief Chip-specific reset cause functions + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef XMEGA_DRIVERS_CPU_RESET_CAUSE_H +#define XMEGA_DRIVERS_CPU_RESET_CAUSE_H + +#include "compiler.h" +#include "ccp.h" + +/** + * \ingroup reset_cause_group + * \defgroup xmega_reset_cause_group XMEGA reset cause + * + * See \ref reset_cause_quickstart + * + * @{ + */ + +/** + * \brief Chip-specific reset cause type capable of holding all chip reset + * causes. Typically reflects the size of the reset cause register. + */ +typedef uint8_t reset_cause_t; + +//! \internal \name Chip-specific reset causes +//@{ +//! \internal External reset cause +#define CHIP_RESET_CAUSE_EXTRST RST_EXTRF_bm +//! \internal brown-out detected reset cause, same as for CPU +#define CHIP_RESET_CAUSE_BOD_IO RST_BORF_bm +//! \internal Brown-out detected reset cause, same as for I/O +#define CHIP_RESET_CAUSE_BOD_CPU RST_BORF_bm +//! \internal On-chip debug system reset cause +#define CHIP_RESET_CAUSE_OCD RST_PDIRF_bm +//! \internal Power-on-reset reset cause +#define CHIP_RESET_CAUSE_POR RST_PORF_bm +//! \internal Software reset reset cause +#define CHIP_RESET_CAUSE_SOFT RST_SRF_bm +//! \internal Spike detected reset cause +#define CHIP_RESET_CAUSE_SPIKE RST_SDRF_bm +//! \internal Watchdog timeout reset cause +#define CHIP_RESET_CAUSE_WDT RST_WDRF_bm +//@} + +static inline reset_cause_t reset_cause_get_causes(void) +{ + return (reset_cause_t)RST.STATUS; +} + +static inline void reset_cause_clear_causes(reset_cause_t causes) +{ + RST.STATUS = causes; +} + +static inline void reset_do_soft_reset(void) +{ + ccp_write_io((void *)&RST.CTRL, RST_SWRST_bm); + + while (1) { + /* Intentionally empty. */ + } +} + +//! @} + +#endif /* XMEGA_DRIVERS_CPU_RESET_CAUSE_H */ diff --git a/DSTAT-temp/src/asf/xmega/drivers/nvm/nvm.c b/DSTAT-temp/src/asf/xmega/drivers/nvm/nvm.c new file mode 100644 index 0000000..af2a445 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/nvm/nvm.c @@ -0,0 +1,757 @@ +/** + * \file + * + * \brief Non Volatile Memory controller driver + * + * Copyright (C) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include "compiler.h" +#include "ccp.h" +#include "nvm.h" +#include + +/** + * \weakgroup nvm_signature_group + * @{ + */ + +/** + * \brief Read the device serial + * + * This function returns the device serial stored in the device. + * + * \note This function is modifying the NVM.CMD register. + * If the application are using program space access in interrupts + * (__flash pointers in IAR EW or pgm_read_byte in GCC) interrupts + * needs to be disabled when running EEPROM access functions. If not + * the program space reads will be corrupted. + * + * \retval storage Pointer to the structure where to store the device serial + */ +void nvm_read_device_serial(struct nvm_device_serial *storage) +{ + storage->lotnum0 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(LOTNUM0)); + storage->lotnum1 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(LOTNUM1)); + storage->lotnum2 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(LOTNUM2)); + storage->lotnum3 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(LOTNUM3)); + storage->lotnum4 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(LOTNUM4)); + storage->lotnum5 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(LOTNUM5)); + + storage->wafnum = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(WAFNUM)); + + storage->coordx0 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(COORDX0)); + storage->coordx1 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(COORDX1)); + storage->coordy0 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(COORDY0)); + storage->coordy1 = nvm_read_production_signature_row( + nvm_get_production_signature_row_offset(COORDY1)); +} + +//! @} + +/** + * \weakgroup nvm_eeprom_group + * @{ + */ + +/** + * \brief Read one byte from EEPROM using IO mapping. + * + * This function reads one byte from EEPROM using IO-mapped access. + * If memory mapped EEPROM is enabled, this function will not work. + * + * \param addr EEPROM address, between 0 and EEPROM_SIZE + * + * \return Byte value read from EEPROM. + */ +uint8_t nvm_eeprom_read_byte(eeprom_addr_t addr) +{ + Assert(addr <= EEPROM_SIZE); + + /* Wait until NVM is ready */ + nvm_wait_until_ready(); + + /* Set address to read from */ + NVM.ADDR2 = 0x00; + NVM.ADDR1 = (addr >> 8) & 0xFF; + NVM.ADDR0 = addr & 0xFF; + + /* Issue EEPROM Read command */ + nvm_issue_command(NVM_CMD_READ_EEPROM_gc); + + return NVM.DATA0; +} + +/** + * \brief Read buffer within the eeprom + * + * \param address the address to where to read + * \param buf pointer to the data + * \param len the number of bytes to read + */ +void nvm_eeprom_read_buffer(eeprom_addr_t address, void *buf, uint16_t len) +{ + nvm_wait_until_ready(); + eeprom_enable_mapping(); + memcpy( buf,(void*)(address+MAPPED_EEPROM_START), len ); + eeprom_disable_mapping(); +} + + +/** + * \brief Write one byte to EEPROM using IO mapping. + * + * This function writes one byte to EEPROM using IO-mapped access. + * If memory mapped EEPROM is enabled, this function will not work. + * This function will cancel all ongoing EEPROM page buffer loading + * operations, if any. + * + * \param address EEPROM address (max EEPROM_SIZE) + * \param value Byte value to write to EEPROM. + */ +void nvm_eeprom_write_byte(eeprom_addr_t address, uint8_t value) +{ + uint8_t old_cmd; + + /* Flush buffer to make sure no unintentional data is written and load + * the "Page Load" command into the command register. + */ + old_cmd = NVM.CMD; + nvm_eeprom_flush_buffer(); + // Wait until NVM is ready + nvm_wait_until_ready(); + + NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc; + + Assert(address <= EEPROM_SIZE); + + // Set address to write to + NVM.ADDR2 = 0x00; + NVM.ADDR1 = (address >> 8) & 0xFF; + NVM.ADDR0 = address & 0xFF; + + // Load data to write, which triggers the loading of EEPROM page buffer + NVM.DATA0 = value; + + /* Issue EEPROM Atomic Write (Erase&Write) command. Load command, write + * the protection signature and execute command. + */ + NVM.CMD = NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc; + nvm_exec(); + NVM.CMD = old_cmd; +} + +/** + * \brief Write buffer within the eeprom + * + * \param address the address to where to write + * \param buf pointer to the data + * \param len the number of bytes to write + */ +void nvm_eeprom_erase_and_write_buffer(eeprom_addr_t address, const void *buf, uint16_t len) +{ + while (len) { + if (((address%EEPROM_PAGE_SIZE)==0) && (len>=EEPROM_PAGE_SIZE)) { + // A full page can be written + nvm_eeprom_load_page_to_buffer((uint8_t*)buf); + nvm_eeprom_atomic_write_page(address/EEPROM_PAGE_SIZE); + address += EEPROM_PAGE_SIZE; + buf = (uint8_t*)buf + EEPROM_PAGE_SIZE; + len -= EEPROM_PAGE_SIZE; + } else { + nvm_eeprom_write_byte(address++, *(uint8_t*)buf); + buf = (uint8_t*)buf + 1; + len--; + } + } +} + + +/** + * \brief Flush temporary EEPROM page buffer. + * + * This function flushes the EEPROM page buffers. This function will cancel + * any ongoing EEPROM page buffer loading operations, if any. + * This function also works for memory mapped EEPROM access. + * + * \note An EEPROM write operations will automatically flush the buffer for you. + * \note The function does not preserve the value of the NVM.CMD register + */ +void nvm_eeprom_flush_buffer(void) +{ + // Wait until NVM is ready + nvm_wait_until_ready(); + + // Flush EEPROM page buffer if necessary + if ((NVM.STATUS & NVM_EELOAD_bm) != 0) { + NVM.CMD = NVM_CMD_ERASE_EEPROM_BUFFER_gc; + nvm_exec(); + } +} + +/** + * \brief Load single byte into temporary page buffer. + * + * This function loads one byte into the temporary EEPROM page buffers. + * If memory mapped EEPROM is enabled, this function will not work. + * Make sure that the buffer is flushed before starting to load bytes. + * Also, if multiple bytes are loaded into the same location, they will + * be ANDed together, thus 0x55 and 0xAA will result in 0x00 in the buffer. + * + * \note Only one page buffer exist, thus only one page can be loaded with + * data and programmed into one page. If data needs to be written to + * different pages, the loading and writing needs to be repeated. + * + * \param byte_addr EEPROM Byte address, between 0 and EEPROM_PAGE_SIZE. + * \param value Byte value to write to buffer. + */ +void nvm_eeprom_load_byte_to_buffer(uint8_t byte_addr, uint8_t value) +{ + uint8_t old_cmd; + old_cmd = NVM.CMD; + + // Wait until NVM is ready + nvm_wait_until_ready(); + + NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc; + + // Set address + NVM.ADDR2 = 0x00; + NVM.ADDR1 = 0x00; + NVM.ADDR0 = byte_addr & 0xFF; + + // Set data, which triggers loading of EEPROM page buffer + NVM.DATA0 = value; + + NVM.CMD = old_cmd; +} + + +/** + * \brief Load entire page into temporary EEPROM page buffer. + * + * This function loads an entire EEPROM page from an SRAM buffer to + * the EEPROM page buffers. If memory mapped EEPROM is enabled, this + * function will not work. Make sure that the buffer is flushed before + * starting to load bytes. + * + * \note Only the lower part of the address is used to address the buffer. + * Therefore, no address parameter is needed. In the end, the data + * is written to the EEPROM page given by the address parameter to the + * EEPROM write page operation. + * + * \param values Pointer to SRAM buffer containing an entire page. + */ +void nvm_eeprom_load_page_to_buffer(const uint8_t *values) +{ + uint8_t old_cmd; + old_cmd = NVM.CMD; + + // Wait until NVM is ready + nvm_wait_until_ready(); + + NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc; + + /* Set address to zero, as only the lower bits matters. ADDR0 is + * maintained inside the loop below. + */ + NVM.ADDR2 = 0x00; + NVM.ADDR1 = 0x00; + + // Load multiple bytes into page buffer + uint8_t i; + for (i = 0; i < EEPROM_PAGE_SIZE; ++i) { + NVM.ADDR0 = i; + NVM.DATA0 = *values; + ++values; + } + NVM.CMD = old_cmd; +} + +/** + * \brief Erase and write bytes from page buffer into EEPROM. + * + * This function writes the contents of an already loaded EEPROM page + * buffer into EEPROM memory. + * + * As this is an atomic write, the page in EEPROM will be erased + * automatically before writing. Note that only the page buffer locations + * that have been loaded will be used when writing to EEPROM. Page buffer + * locations that have not been loaded will be left untouched in EEPROM. + * + * \param page_addr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGE_SIZE + */ +void nvm_eeprom_atomic_write_page(uint8_t page_addr) +{ + // Wait until NVM is ready + nvm_wait_until_ready(); + + // Calculate page address + uint16_t address = (uint16_t)(page_addr * EEPROM_PAGE_SIZE); + + Assert(address <= EEPROM_SIZE); + + // Set address + NVM.ADDR2 = 0x00; + NVM.ADDR1 = (address >> 8) & 0xFF; + NVM.ADDR0 = address & 0xFF; + + // Issue EEPROM Atomic Write (Erase&Write) command + nvm_issue_command(NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc); +} + +/** + * \brief Write (without erasing) EEPROM page. + * + * This function writes the contents of an already loaded EEPROM page + * buffer into EEPROM memory. + * + * As this is a split write, the page in EEPROM will _not_ be erased + * before writing. + * + * \param page_addr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGE_SIZE + */ +void nvm_eeprom_split_write_page(uint8_t page_addr) +{ + // Wait until NVM is ready + nvm_wait_until_ready(); + + // Calculate page address + uint16_t address = (uint16_t)(page_addr * EEPROM_PAGE_SIZE); + + Assert(address <= EEPROM_SIZE); + + // Set address + NVM.ADDR2 = 0x00; + NVM.ADDR1 = (address >> 8) & 0xFF; + NVM.ADDR0 = address & 0xFF; + + // Issue EEPROM Split Write command + nvm_issue_command(NVM_CMD_WRITE_EEPROM_PAGE_gc); +} + +/** + * \brief Fill temporary EEPROM page buffer with value. + * + * This fills the the EEPROM page buffers with a given value. + * If memory mapped EEPROM is enabled, this function will not work. + * + * \note Only the lower part of the address is used to address the buffer. + * Therefore, no address parameter is needed. In the end, the data + * is written to the EEPROM page given by the address parameter to the + * EEPROM write page operation. + * + * \param value Value to copy to the page buffer. + */ +void nvm_eeprom_fill_buffer_with_value(uint8_t value) +{ + uint8_t old_cmd; + old_cmd = NVM.CMD; + + nvm_eeprom_flush_buffer(); + // Wait until NVM is ready + nvm_wait_until_ready(); + + NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc; + + /* Set address to zero, as only the lower bits matters. ADDR0 is + * maintained inside the loop below. + */ + NVM.ADDR2 = 0x00; + NVM.ADDR1 = 0x00; + + // Load multiple bytes into page buffer + uint8_t i; + for (i = 0; i < EEPROM_PAGE_SIZE; ++i) { + NVM.ADDR0 = i; + NVM.DATA0 = value; + } + NVM.CMD = old_cmd; +} + +/** + * \brief Erase bytes from EEPROM page. + * + * This function erases bytes from one EEPROM page, so that every location + * written to in the page buffer reads 0xFF. + * + * \param page_addr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGE_SIZE + */ +void nvm_eeprom_erase_bytes_in_page(uint8_t page_addr) +{ + // Wait until NVM is ready + nvm_wait_until_ready(); + + // Calculate page address + uint16_t address = (uint16_t)(page_addr * EEPROM_PAGE_SIZE); + + Assert(address <= EEPROM_SIZE); + + // Set address + NVM.ADDR2 = 0x00; + NVM.ADDR1 = (address >> 8) & 0xFF; + NVM.ADDR0 = address & 0xFF; + + // Issue EEPROM Erase command + nvm_issue_command(NVM_CMD_ERASE_EEPROM_PAGE_gc); +} + +/** + * \brief Erase EEPROM page. + * + * This function erases one EEPROM page, so that every location reads 0xFF. + * + * \param page_addr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGE_SIZE + */ +void nvm_eeprom_erase_page(uint8_t page_addr) +{ + // Mark all addresses to be deleted + nvm_eeprom_fill_buffer_with_value(0xff); + // Erase bytes + nvm_eeprom_erase_bytes_in_page(page_addr); +} + + +/** + * \brief Erase bytes from all EEPROM pages. + * + * This function erases bytes from all EEPROM pages, so that every location + * written to in the page buffer reads 0xFF. + */ +void nvm_eeprom_erase_bytes_in_all_pages(void) +{ + // Wait until NVM is ready + nvm_wait_until_ready(); + + // Issue EEPROM Erase All command + nvm_issue_command(NVM_CMD_ERASE_EEPROM_gc); +} + +/** + * \brief Erase entire EEPROM memory. + * + * This function erases the entire EEPROM memory block to 0xFF. + */ +void nvm_eeprom_erase_all(void) +{ + // Mark all addresses to be deleted + nvm_eeprom_fill_buffer_with_value(0xff); + // Erase all pages + nvm_eeprom_erase_bytes_in_all_pages(); +} + +//! @} + + +//! @} + + +/** + * \weakgroup nvm_flash_group + * @{ + */ + +/** + * \brief Issue flash range CRC command + * + * This function sets the FLASH range CRC command in the NVM.CMD register. + * It then loads the start and end byte address of the part of FLASH to + * generate a CRC-32 for into the ADDR and DATA registers and finally performs + * the execute command. + * + * \note Should only be called from the CRC module. The function saves and + * restores the NVM.CMD register, but if this + * function is called from an interrupt, interrupts must be disabled + * before this function is called. + * + * \param start_addr end byte address + * \param end_addr start byte address + */ +void nvm_issue_flash_range_crc(flash_addr_t start_addr, flash_addr_t end_addr) +{ + uint8_t old_cmd; + // Save current nvm command + old_cmd = NVM.CMD; + + // Load the NVM CMD register with the Flash Range CRC command + NVM.CMD = NVM_CMD_FLASH_RANGE_CRC_gc; + + // Load the start byte address in the NVM Address Register + NVM.ADDR0 = start_addr & 0xFF; + NVM.ADDR1 = (start_addr >> 8) & 0xFF; +#if (FLASH_SIZE >= 0x10000UL) + NVM.ADDR2 = (start_addr >> 16) & 0xFF; +#endif + + // Load the end byte address in NVM Data Register + NVM.DATA0 = end_addr & 0xFF; + NVM.DATA1 = (end_addr >> 8) & 0xFF; +#if (FLASH_SIZE >= 0x10000UL) + NVM.DATA2 = (end_addr >> 16) & 0xFF; +#endif + + // Execute command + ccp_write_io((uint8_t *)&NVM.CTRLA, NVM_CMDEX_bm); + + // Restore command register + NVM.CMD = old_cmd; +} + +/** + * \brief Read buffer within the application section + * + * \param address the address to where to read + * \param buf pointer to the data + * \param len the number of bytes to read + */ +void nvm_flash_read_buffer(flash_addr_t address, void *buf, uint16_t len) +{ +#if (FLASH_SIZE>0x10000) + uint32_t opt_address = address; +#else + uint16_t opt_address = (uint16_t)address; +#endif + nvm_wait_until_ready(); + while ( len ) { + *(uint8_t*)buf = nvm_flash_read_byte(opt_address); + buf=(uint8_t*)buf+1; + opt_address++; + len--; + } +} + +/** + * \brief Read buffer within the user section + * + * \param address the address to where to read + * \param buf pointer to the data + * \param len the number of bytes to read + */ +void nvm_user_sig_read_buffer(flash_addr_t address, void *buf, uint16_t len) +{ + uint16_t opt_address = (uint16_t)address&(FLASH_PAGE_SIZE-1); + while ( len ) { + *(uint8_t*)buf = nvm_read_user_signature_row(opt_address); + buf=(uint8_t*)buf+1; + opt_address++; + len--; + } +} + +/** + * \brief Write specific parts of user flash section + * + * \param address the address to where to write + * \param buf pointer to the data + * \param len the number of bytes to write + * \param b_blank_check if True then the page flash is checked before write + * to run or not the erase page command. + * + * Set b_blank_check to false if all application flash is erased before. + */ +void nvm_user_sig_write_buffer(flash_addr_t address, const void *buf, + uint16_t len, bool b_blank_check) +{ + uint16_t w_value; + uint16_t page_pos; + uint16_t opt_address = (uint16_t)address; + bool b_flag_erase = false; + + while ( len ) { + for (page_pos=0; page_pos0x10000) + uint32_t page_address; + uint32_t opt_address = address; +#else + uint16_t page_address; + uint16_t opt_address = (uint16_t)address; +#endif + + // Compute the start of the page to be modified + page_address = opt_address-(opt_address%FLASH_PAGE_SIZE); + + // For each page + while ( len ) { + b_flag_erase = false; + + nvm_wait_until_ready(); + for (page_pos=0; page_pos +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup nvm_group NVM driver + * + * See \ref xmega_nvm_quickstart + * + * \brief Low-level driver implementation for the AVR XMEGA Non Volatile + * Memory Controller (NVM). + * + * The XMEGA NVM controller interfaces the internal non-volatile memories + * in the XMEGA devices. Program memory, EEPROM and signature row is can be + * interfaced by the module. See the documentation of each sub-module for + * more information. + * + * \note If using GCC and the flash sub-module, remember to configure + * the boot section in the make file. More information in the sub-module + * documentation. + * + * \section xmega_nvm_quickstart_section Quick Start Guide + * See \ref xmega_nvm_quickstart + */ + +/** + * \defgroup nvm_generic_group NVM driver generic module handling + * \ingroup nvm_group + * \brief Support functions for the NVM driver. + * + * These functions are helper functions for the functions of the + * \ref nvm_group "NVM driver". + * + * @{ + */ + +/** + * \brief Wait for any NVM access to finish. + * + * This function is blocking and waits for any NVM access to finish. + * Use this function before any NVM accesses, if you are not certain that + * any previous operations are finished yet. + */ +static inline void nvm_wait_until_ready( void ) +{ + do { + // Block execution while waiting for the NVM to be ready + } while ((NVM.STATUS & NVM_NVMBUSY_bm) == NVM_NVMBUSY_bm); +} + +/** + * \brief Non-Volatile Memory Execute Command + * + * This function sets the CCP register before setting the CMDEX bit in the + * NVM.CTRLA register. + * + * \note The correct NVM command must be set in the NVM.CMD register before + * calling this function. + */ +static inline void nvm_exec(void) +{ + ccp_write_io((uint8_t *)&NVM.CTRLA, NVM_CMDEX_bm); +} + +/** + * \brief Non-Volatile Memory Execute Specific Command + * + * This function sets a command in the NVM.CMD register, then performs an + * execute command by writing the CMDEX bit to the NVM.CTRLA register. + * + * \note The function saves and restores the NVM.CMD register, but if this + * function is called from an interrupt, interrupts must be disabled + * before this function is called. + * + * \param nvm_command NVM Command to execute. + */ +static inline void nvm_issue_command(NVM_CMD_t nvm_command) +{ + uint8_t old_cmd; + + old_cmd = NVM.CMD; + NVM.CMD = nvm_command; + ccp_write_io((uint8_t *)&NVM.CTRLA, NVM_CMDEX_bm); + NVM.CMD = old_cmd; +} + +/** + * \brief Read one byte using the LDI instruction + * \internal + * + * This function sets the specified NVM_CMD, reads one byte using at the + * specified byte address with the LPM instruction. NVM_CMD is restored after + * use. + * + * \note Interrupts should be disabled before running this function + * if program memory/NVM controller is accessed from ISRs. + * + * \param nvm_cmd NVM command to load before running LPM + * \param address Byte offset into the signature row + */ +uint8_t nvm_read_byte(uint8_t nvm_cmd, uint16_t address); + + +/** + * \brief Perform SPM write + * \internal + * + * This function sets the specified NVM_CMD, sets CCP and then runs the SPM + * instruction to write to flash. + * + * \note Interrupts should be disabled before running this function + * if program memory/NVM controller is accessed from ISRs. + * + * \param addr Address to perform the SPM on. + * \param nvm_cmd NVM command to use in the NVM_CMD register + */ +void nvm_common_spm(uint32_t addr, uint8_t nvm_cmd); + +//! @} + +/** + * \defgroup nvm_signature_group NVM driver signature handling + * \ingroup nvm_group + * \brief Handling of signature rows + * + * Functions for handling signature rows. The following is supported: + * - Reading values from production and user signature row + * - Reading device id + * - Reading device revision + * - Reading device serial + * + * \note Some of these functions are modifying the NVM.CMD register. + * If the application are using program space access in interrupts + * (__flash pointers in IAR EW or pgm_read_byte in GCC) interrupts + * needs to be disabled when running EEPROM access functions. If not, + * the program space reads will be corrupted. See documentation for + * each individual function. + * \note Do not use the functions of this module in an interrupt service + * routine (ISR), since the functions can take several milliseconds to + * complete and hence block the interrupt for several milliseconds. + * In addition the functions of this module are modifying the page buffer + * which will corrupt any ongoing EEPROM handing used outside an ISR. + * @{ + */ + +/** + * \brief Structure containing the device ID + * + * This structure can be used to store the device ID of a device. + */ +struct nvm_device_id { + union { + struct { + uint8_t devid0; + uint8_t devid1; + uint8_t devid2; + }; + uint8_t byte[3]; + }; +}; + +/** + * \brief Structure containing the device serial + * + * This structure can be used to store the serial number of a device. + */ +struct nvm_device_serial { + union { + struct { + uint8_t lotnum0; + uint8_t lotnum1; + uint8_t lotnum2; + uint8_t lotnum3; + uint8_t lotnum4; + uint8_t lotnum5; + uint8_t wafnum; + uint8_t coordx0; + uint8_t coordx1; + uint8_t coordy0; + uint8_t coordy1; + }; + uint8_t byte[11]; + }; +}; + +/** + * \brief Get offset of calibration bytes in the production signature row + * + * \param regname Name of register within the production signature row + * \retval Offset of register into the production signature row + */ +#if defined(__GNUC__) +# define nvm_get_production_signature_row_offset(regname) \ + offsetof(NVM_PROD_SIGNATURES_t, regname) +#elif defined(__ICCAVR__) +# define nvm_get_production_signature_row_offset(regname) (regname##_offset) +#else +# error Unknown compiler +#endif + + +/** + * \brief Read one byte from the production signature row + * + * This function reads one byte from the production signature row of the device + * at the given address. + * + * \note This function is modifying the NVM.CMD register. + * If the application are using program space access in interrupts + * (__flash pointers in IAR EW or pgm_read_byte in GCC) interrupts + * needs to be disabled when running EEPROM access functions. If not + * the program space reads will be corrupted. + * + * \param address Byte offset into the signature row + */ +static inline uint8_t nvm_read_production_signature_row(uint8_t address) +{ + return nvm_read_byte(NVM_CMD_READ_CALIB_ROW_gc, address); +} + +/** + * \brief Read one byte from the user signature row + * + * This function reads one byte from the user signature row of the device + * at the given address. + * + * \note This function is modifying the NVM.CMD register. + * If the application are using program space access in interrupts + * (__flash pointers in IAR EW or pgm_read_byte in GCC) interrupts + * needs to be disabled when running EEPROM access functions. If not + * the program space reads will be corrupted. + * + * \param address Byte offset into the signature row + */ +static inline uint8_t nvm_read_user_signature_row(uint16_t address) +{ + return nvm_read_byte(NVM_CMD_READ_USER_SIG_ROW_gc, address); +} + +/** + * \brief Read the device id + * + * This function returns the device ID stored in the device. + * + * \retval storage Pointer to the structure where to store the device id + */ +static inline void nvm_read_device_id(struct nvm_device_id *storage) +{ + storage->devid0 = MCU.DEVID0; + storage->devid1 = MCU.DEVID1; + storage->devid2 = MCU.DEVID2; +} + +/** + * \brief Read the device revision + * + * This function returns the device revision stored in the device. + * + * \retval unsigned 8 bit value with the current device revision. + */ +static inline uint8_t nvm_read_device_rev(void) +{ + return MCU.REVID; +} + +void nvm_read_device_serial(struct nvm_device_serial *storage); + +//! @} + + +/** + * \defgroup nvm_eeprom_group NVM driver EEPROM handling + * \ingroup nvm_group + * \brief Functions for handling internal EEPROM memory. + * + * The internal EEPROM can be used to store data that will persist after + * power is removed. This can typically be used to store calibration data, + * application state, encryption keys or other data that need to be preserved + * when power is removed. + * + * The functions in this module uses IO register access to manipulate the + * EEPROM. + * + * \note The functions in this module are modifying the NVM.CMD register. + * If the application are using program space access in interrupts + * (__flash pointers in IAR EW or pgm_read_byte in GCC) interrupts + * needs to be disabled when running EEPROM access functions. If not + * the program space reads will be corrupted. + * @{ + */ + +#ifndef EEPROM_PAGE_SIZE +# if XMEGA_A || XMEGA_AU || XMEGA_B || XMEGA_C || XMEGA_D +# define EEPROM_PAGE_SIZE 32 +# else +# error Unknown EEPROM page size +# endif +#endif + +#ifndef CONFIG_NVM_IGNORE_XMEGA_A3_D3_REVB_ERRATA +# if XMEGA_A3 || XMEGA_D3 +# error This NVM driver does not support rev B of XMEGA A3/D3 devices. \ + Set CONFIG_NVM_IGNORE_XMEGA_A3_D3_REVB_ERRATA to disable this message +# endif +#endif + +/** + * Data type for holding eeprom memory addresses. + */ +typedef uint16_t eeprom_addr_t; + + +/*! \brief Enable EEPROM mapping into data space. + * + * This macro enables mapping of EEPROM into data space. + * EEPROM starts at EEPROM_START in data memory. Read access + * can be done similar to ordinary SRAM access. + * + * \note This disables IO-mapped access to EEPROM, although page erase and + * write operations still needs to be done through IO register. + */ +static inline void eeprom_enable_mapping(void) +{ + NVM_CTRLB = NVM_CTRLB | NVM_EEMAPEN_bm; +} + + +/*! \brief Disable EEPROM mapping into data space. + * + * This macro disables mapping of EEPROM into data space. + * IO mapped access is now enabled. + */ +static inline void eeprom_disable_mapping(void) +{ + NVM_CTRLB = NVM_CTRLB & ~NVM_EEMAPEN_bm; +} + + +uint8_t nvm_eeprom_read_byte(eeprom_addr_t addr); +void nvm_eeprom_write_byte(eeprom_addr_t address, uint8_t value); +void nvm_eeprom_read_buffer(eeprom_addr_t address, void *buf, uint16_t len); +void nvm_eeprom_erase_and_write_buffer(eeprom_addr_t address, const void *buf, uint16_t len); + +void nvm_eeprom_flush_buffer(void); +void nvm_eeprom_load_byte_to_buffer(uint8_t byte_addr, uint8_t value); +void nvm_eeprom_load_page_to_buffer(const uint8_t *values); +void nvm_eeprom_atomic_write_page(uint8_t page_addr); +void nvm_eeprom_split_write_page(uint8_t page_addr); +void nvm_eeprom_fill_buffer_with_value(uint8_t value); +void nvm_eeprom_erase_bytes_in_page(uint8_t page_addr); +void nvm_eeprom_erase_page(uint8_t page_addr); +void nvm_eeprom_erase_bytes_in_all_pages(void); +void nvm_eeprom_erase_all(void); + +//! @} + +/** + * \defgroup nvm_flash_group NVM driver flash handling + * \ingroup nvm_group + * \brief Functions for handling internal flash memory. + * + * The internal flash memory on the XMEGA devices consists of the application + * section, the application table section and the bootloader section. + * All these sections can store program code for the MCU, but if there is + * available space, they can be used for storing other persistent data. + * + * Writing the flash memory can only be done one page at a time. It consists + * of loading the data to the internal page buffer and then running one of + * the write commands. If the page has not been erased before writing, the + * data will not be written correctly. + * + * In order to be able to write to flash memory the programming commands need + * to be run from the boot section. + * - When using IAR this is handled automatically by the linker script. + * - When using GCC this needs to be specified manually in the make files. For + * example the ATxmega128A1 has the boot section at the word address 0x10000 + * the corresponding byte address of 0x20000 needs to be added to the + * config.mk makefile: + * LDFLAGS += -Wl,--section-start=.BOOT=0x20000 + * See the device datasheet for the correct address for other devices. + * + * \note If using GCC and the flash sub-module, remember to configure + * the boot section in the make file. + * + * \note The functions in this module are modifying the NVM.CMD register. + * If the application are using program space access in interrupts + * (__flash pointers in IAR EW or pgm_read_byte in GCC) interrupts + * needs to be disabled when running EEPROM access functions. If not + * the program space reads will be corrupted. + * @{ + */ + +/** + * \brief Size of a flash page in bytes + * + * The page size in bytes taken from the toolchain header files. + * + * \note Page size is currently missing from the IAR header files, so it needs + * to be defined in the driver until it is fixed. + */ +#ifdef __DOXYGEN__ +# define FLASH_SIZE +# define FLASH_PAGE_SIZE +#else + +// 16K devices +# if AVR8_PART_IS_DEFINED(ATxmega16A4) | \ + AVR8_PART_IS_DEFINED(ATxmega16A4U) | \ + AVR8_PART_IS_DEFINED(ATxmega16D4) | \ + AVR8_PART_IS_DEFINED(ATxmega16C4) +# define FLASH_SIZE (16*1024L) +# define FLASH_PAGE_SIZE (256) + +// 32K devices +# elif AVR8_PART_IS_DEFINED(ATxmega32A4) | \ + AVR8_PART_IS_DEFINED(ATxmega32A4U) | \ + AVR8_PART_IS_DEFINED(ATxmega32D4) | \ + AVR8_PART_IS_DEFINED(ATxmega32C4) +# define FLASH_SIZE (32*1024L) +# define FLASH_PAGE_SIZE (256) + +// 64K devices +# elif AVR8_PART_IS_DEFINED(ATxmega64A1) | \ + AVR8_PART_IS_DEFINED(ATxmega64A1U) | \ + AVR8_PART_IS_DEFINED(ATxmega64A3) | \ + AVR8_PART_IS_DEFINED(ATxmega64A3U) | \ + AVR8_PART_IS_DEFINED(ATxmega64A4U) | \ + AVR8_PART_IS_DEFINED(ATxmega64B1) | \ + AVR8_PART_IS_DEFINED(ATxmega64B3) | \ + AVR8_PART_IS_DEFINED(ATxmega64C3) | \ + AVR8_PART_IS_DEFINED(ATxmega64D3) | \ + AVR8_PART_IS_DEFINED(ATxmega64D4) +# define FLASH_SIZE (64*1024L) +# define FLASH_PAGE_SIZE (256) + +// 128K devices +# elif AVR8_PART_IS_DEFINED(ATxmega128A1) | \ + AVR8_PART_IS_DEFINED(ATxmega128A1U) | \ + AVR8_PART_IS_DEFINED(ATxmega128A3) | \ + AVR8_PART_IS_DEFINED(ATxmega128A3U) | \ + AVR8_PART_IS_DEFINED(ATxmega128C3) | \ + AVR8_PART_IS_DEFINED(ATxmega128D3) | \ + AVR8_PART_IS_DEFINED(ATxmega128D4) +# define FLASH_SIZE (128*1024L) +# define FLASH_PAGE_SIZE (512) + +# elif AVR8_PART_IS_DEFINED(ATxmega128A4U) | \ + AVR8_PART_IS_DEFINED(ATxmega128B1) | \ + AVR8_PART_IS_DEFINED(ATxmega128B3) +# define FLASH_SIZE (128*1024L) +# define FLASH_PAGE_SIZE (256) + +// 192K devices +# elif AVR8_PART_IS_DEFINED(ATxmega192A3U) | \ + AVR8_PART_IS_DEFINED(ATxmega192D3) +# define FLASH_SIZE (192*1024L) +# define FLASH_PAGE_SIZE (512) + +// 256K devices +# elif AVR8_PART_IS_DEFINED(ATxmega256A3) | \ + AVR8_PART_IS_DEFINED(ATxmega256A3U) | \ + AVR8_PART_IS_DEFINED(ATxmega256A3B) | \ + AVR8_PART_IS_DEFINED(ATxmega256A3BU) | \ + AVR8_PART_IS_DEFINED(ATxmega256C3) | \ + AVR8_PART_IS_DEFINED(ATxmega256D3) +# define FLASH_SIZE (256*1024L) +# define FLASH_PAGE_SIZE (512) + +// 384K devices +# elif AVR8_PART_IS_DEFINED(ATxmega384C3) +# define FLASH_SIZE (384*1024L) +# define FLASH_PAGE_SIZE (512) +# elif AVR8_PART_IS_DEFINED(ATxmega384D3) +# define FLASH_SIZE (384*1024L) +# define FLASH_PAGE_SIZE (512) +# else +# error Flash page size needs to be defined. +# endif +#endif + +/** + * Data type for holding flash memory addresses. + * + */ +#if (FLASH_SIZE >= 0x10000UL) // Note: Xmega with 64KB of flash have 4KB boot flash +typedef uint32_t flash_addr_t; +#else +typedef uint16_t flash_addr_t; +#endif + +/** + * Flash pointer type to use for accessing flash memory with IAR + */ +#if (FLASH_SIZE >= 0x10000UL) // Note: Xmega with 64KB of flash have 4KB boot flash +# define IAR_FLASH_PTR __farflash +#else +# define IAR_FLASH_PTR __flash +#endif + +/** + * \brief Load byte from flash memory + * + * Load one word of flash using byte addressing. IAR has __flash pointers + * and GCC have pgm_read_byte_xx functions which load data from flash memory. + * This function used for compatibility between the compilers. + * + * \param addr Byte address to load + * \return Byte from program memory + */ +static inline uint8_t nvm_flash_read_byte(flash_addr_t addr) +{ +#if defined(__GNUC__) + return pgm_read_byte_far(addr); +#elif defined(__ICCAVR__) + uint8_t IAR_FLASH_PTR *flashptr = (uint8_t IAR_FLASH_PTR *)addr; + return *flashptr; +#else +# error Unknown compiler +#endif +} + +/** + * \brief Load word from flash memory + * + * Load one word of flash using byte addressing. IAR has __flash pointers + * and GCC have pgm_read_byte_xx functions which load data from flash memory. + * This function used for compatibility between the compilers. + * + * \param addr Byte address to load (last bit is ignored) + * \return Word from program memory + */ +static inline uint16_t nvm_flash_read_word(flash_addr_t addr) +{ +#if defined(__GNUC__) + return pgm_read_word_far(addr); +#elif defined(__ICCAVR__) + uint16_t IAR_FLASH_PTR *flashptr = (uint16_t IAR_FLASH_PTR *)addr; + return *flashptr; +#endif +} + + +/** + * \brief Flush flash page buffer + * + * Clear the NVM controller page buffer for flash. This needs to be called + * before using \ref nvm_flash_load_word_to_buffer if it has not already been + * cleared. + * + */ +static inline void nvm_flash_flush_buffer(void) +{ + nvm_wait_until_ready(); + nvm_common_spm(0, NVM_CMD_ERASE_FLASH_BUFFER_gc); +} + + +/** + * \brief Load word into flash page buffer + * + * Clear the NVM controller page buffer for flash. This needs to be called + * before using \ref nvm_flash_load_word_to_buffer if it has not already been + * cleared. + * + * \param word_addr Address to store data. The upper bits beyond the page size + * is ignored. \ref FLASH_PAGE_SIZE + * \param data Data word to load into the page buffer + */ +void nvm_flash_load_word_to_buffer(uint32_t word_addr, uint16_t data); + + +/** + * \brief Erase entire application section + * + * Erase all of the application section. + */ +static inline void nvm_flash_erase_app(void) +{ + nvm_wait_until_ready(); + nvm_common_spm(0, NVM_CMD_ERASE_APP_gc); +} + +/** + * \brief Erase a page within the application section + * + * Erase one page within the application section + * + * \param page_addr Byte address to the page to delete + */ +static inline void nvm_flash_erase_app_page(flash_addr_t page_addr) +{ + nvm_wait_until_ready(); + nvm_common_spm(page_addr, NVM_CMD_ERASE_APP_PAGE_gc); +} + +/** + * \brief Write a page within the application section + * + * Write a page within the application section with the data stored in the + * page buffer. The page needs to be erased before the write to avoid + * corruption of the data written. + * + * \param page_addr Byte address to the page to delete + */ +static inline void nvm_flash_split_write_app_page(flash_addr_t page_addr) +{ + nvm_wait_until_ready(); + nvm_common_spm(page_addr, NVM_CMD_WRITE_APP_PAGE_gc); +} + +/** + * \brief Erase and write a page within the application section + * + * Erase and the write a page within the application section with the data + * stored in the page buffer. Erase and write is done in an atomic operation. + * + * \param page_addr Byte address to the page to delete + */ +static inline void nvm_flash_atomic_write_app_page(flash_addr_t page_addr) +{ + nvm_wait_until_ready(); + nvm_common_spm(page_addr, NVM_CMD_ERASE_WRITE_APP_PAGE_gc); +} + +void nvm_issue_flash_range_crc(flash_addr_t start_addr, flash_addr_t end_addr); + +void nvm_flash_read_buffer(flash_addr_t address, void *buf, uint16_t len); + +void nvm_flash_erase_and_write_buffer(flash_addr_t address, const void *buf, + uint16_t len, bool b_blank_check); + +/** + * \brief Erase a page within the boot section + * + * Erase one page within the boot section + * + * \param page_addr Byte address to the page to delete + */ +static inline void nvm_flash_erase_boot_page(flash_addr_t page_addr) +{ + nvm_wait_until_ready(); + nvm_common_spm(page_addr, NVM_CMD_ERASE_BOOT_PAGE_gc); +} + +/** + * \brief Write a page within the boot section + * + * Write a page within the boot section with the data stored in the + * page buffer. The page needs to be erased before the write to avoid + * corruption of the data written. + * + * \param page_addr Byte address to the page to delete + */ +static inline void nvm_flash_split_write_boot_page(flash_addr_t page_addr) +{ + nvm_wait_until_ready(); + nvm_common_spm(page_addr, NVM_CMD_WRITE_BOOT_PAGE_gc); +} + +/** + * \brief Erase and write a page within the boot section + * + * Erase and the write a page within the boot section with the data + * stored in the page buffer. Erase and write is done in an atomic operation. + * + * \param page_addr Byte address to the page to delete + */ +static inline void nvm_flash_atomic_write_boot_page(flash_addr_t page_addr) +{ + nvm_wait_until_ready(); + nvm_common_spm(page_addr, NVM_CMD_ERASE_WRITE_BOOT_PAGE_gc); +} + +void nvm_user_sig_read_buffer(flash_addr_t address, void *buf, uint16_t len); +void nvm_user_sig_write_buffer(flash_addr_t address, const void *buf, + uint16_t len, bool b_blank_check); + +/** + * \brief Erase the user calibration section page + * + * Erase the user calibration section page. There is only one page, so no + * parameters are needed. + */ +static inline void nvm_flash_erase_user_section(void) +{ + nvm_wait_until_ready(); + nvm_common_spm(0, NVM_CMD_ERASE_USER_SIG_ROW_gc); +} + +/** + * \brief Write the user calibration section page + * + * Write a the user calibration section page with the data stored in the + * page buffer. The page needs to be erased before the write to avoid + * corruption of the data written. There is only one page, so no + * parameters are needed. + */ +static inline void nvm_flash_write_user_page(void) +{ + nvm_wait_until_ready(); + nvm_common_spm(0, NVM_CMD_WRITE_USER_SIG_ROW_gc); +} + +//! @} + +/** + * \defgroup nvm_fuse_lock_group NVM driver fuse and lock bits handling + * \ingroup nvm_group + * \brief Functions for reading fuses and writing lock bits. + * + * The Fuses are used to set important system functions and can only be written + * from an external programming interface. The application software can read + * the fuses. The fuses are used to configure reset sources such as Brown-out + * Detector and Watchdog, Start-up configuration, JTAG enable and JTAG user ID. + * + * The Lock bits are used to set protection level on the different flash + * sections. They are used to block read and/or write on the different flash + * sections. Lock bits can be written from en external programmer and from the + * application software to set a more strict protection level, but not to set a + * less strict protection level. Chip erase is the only way to erase the lock + * bits. The lock bits are erased after the rest of the flash memory is erased. + * An unprogrammed fuse or lock bit will have the value one, while a programmed + * fuse or lock bit will have the value zero. + * Both fuses and lock bits are reprogrammable like the Flash Program memory. + * + * \note The functions in this module are modifying the NVM.CMD register. + * If the application are using program space access in interrupts + * (__flash pointers in IAR EW or pgm_read_byte in GCC) interrupts + * needs to be disabled when running EEPROM access functions. If not + * the program space reads will be corrupted. + * @{ + */ + +// The different fuse bytes +enum fuse_byte_t { + FUSEBYTE0 = 0, + FUSEBYTE1 = 1, + FUSEBYTE2 = 2, + FUSEBYTE3 = 3, // not used on current devices + FUSEBYTE4 = 4, + FUSEBYTE5 = 5, +}; + +uint8_t nvm_fuses_read(enum fuse_byte_t fuse); + +/** + * \brief Program the lock bits. + * + * Program the lock bits to the given values. Lock bits can only be programmed + * to a more secure setting than previously programmed. To clear lock bits, a + * flash erase has to be issued. + * + * \param blbb_lock Boot loader section lock bits to program + * \param blba_lock Application section lock bits to program + * \param blbat_lock Application table section lock bits to program + * \param lb_lock Flash/eeprom lock bits to program + */ +static inline void nvm_lock_bits_write(enum NVM_BLBB_enum blbb_lock, + enum NVM_BLBA_enum blba_lock, enum NVM_BLBAT_enum blbat_lock, + enum NVM_LB_enum lb_lock) +{ + nvm_wait_until_ready(); + NVM.DATA0 = (uint8_t)blbb_lock | (uint8_t)blba_lock | (uint8_t)blbat_lock | + (uint8_t)lb_lock; + nvm_issue_command(NVM_CMD_WRITE_LOCK_BITS_gc); +} + +/** + * \brief Program the BLBB lock bits. + * + * Program the lock bits for the boot loader section (BLBB). Other lock bits + * (BLBA, BLBAT and LB) are not altered (ie. programmed to NOLOCK). + * + * \param blbb_lock Boot loader section lock bits to program + */ +static inline void nvm_blbb_lock_bits_write(enum NVM_BLBB_enum blbb_lock) +{ + nvm_lock_bits_write(blbb_lock, NVM_BLBA_NOLOCK_gc, NVM_BLBAT_NOLOCK_gc, + NVM_LB_NOLOCK_gc); +} + +/** + * \brief Program the BLBA lock bits. + * + * Program the lock bits for the application section (BLBA). Other lock bits + * (BLBB, BLBAT and LB) are not altered (ie. programmed to NOLOCK). + * + * \param blba_lock Application section lock bits to program + */ +static inline void nvm_blba_lock_bits_write(enum NVM_BLBA_enum blba_lock) +{ + nvm_lock_bits_write(NVM_BLBB_NOLOCK_gc, blba_lock, NVM_BLBAT_NOLOCK_gc, + NVM_LB_NOLOCK_gc); +} + +/** + * \brief Program the BLBAT lock bits. + * + * Program the lock bits for the application table section (BLBAT). Other lock + * bits (BLBB, BLBA and LB) are not altered (ie. programmed to NOLOCK). + * + * \param blbat_lock Application table section lock bits to program + */ +static inline void nvm_blbat_lock_bits_write(enum NVM_BLBAT_enum blbat_lock) +{ + nvm_lock_bits_write(NVM_BLBB_NOLOCK_gc, NVM_BLBA_NOLOCK_gc, blbat_lock, + NVM_LB_NOLOCK_gc); +} + +/** + * \brief Program the LB lock bits. + * + * Program the lock bits for the flash and eeprom (LB). Other lock bits + * (BLBB, BLBA and BLBAT) are not altered (ie. programmed to NOLOCK). + * + * \param lb_lock Flash/eeprom lock bits to program + */ +static inline void nvm_lb_lock_bits_write(enum NVM_LB_enum lb_lock) +{ + nvm_lock_bits_write(NVM_BLBB_NOLOCK_gc, NVM_BLBA_NOLOCK_gc, + NVM_BLBAT_NOLOCK_gc, lb_lock); +} + +//! @} + +/** + * \page xmega_nvm_quickstart Quick Start Guide for the XMEGA NVM Driver + * + * This is the quick start guide for the \ref nvm_group "NVM Driver", with + * step-by-step instructions on how to configure and use the driver for + * specific use cases. + * + * The section described below can be compiled into e.g. the main application + * loop or any other function that will need to interface non-volatile memory. + * + * \section xmega_nvm_quickstart_basic Basic usage of the NVM driver + * This section will present three use cases of the NVM driver. The first will + * write a page to EEPROM and verify that it has been written, the second will + * access the BOD-level fuse to verify that the level is correctly set, and the + * third will read a chunk from the user signature row. + * + * \section xmega_nvm_quickstart_eeprom_case Use case 1: EEPROM + * + * The NVM driver has functions for interfacing many types of non-volatile + * memory, including flash, EEPROM, fuses and lock bits. The example code + * below will write a page to the internal EEPROM, and read it back to verify, + * using memory mapped I/O. + * + * \section xmega_nvm_quickstart_eeprom_case_setup_steps Setup steps + * There are no setup steps required for this use case. + * + * \subsection nvm_quickstart_eeprom_case_example_code Example code + * + * \code + * #define EXAMPLE_PAGE 2 + * #define EXAMPLE_ADDR EXAMPLE_PAGE * EEPROM_PAGE_SIZE + * + * uint8_t write_page[EEPROM_PAGE_SIZE]; + * uint8_t read_page[EEPROM_PAGE_SIZE]; + * + * fill_page_with_known_data(write_page); + * fill_page_with_zeroes(read_page); + * + * nvm_eeprom_load_page_to_buffer(write_page); + * nvm_eeprom_atomic_write_page(EXAMPLE_PAGE); + * + * nvm_eeprom_read_buffer(EXAMPLE_ADDR, + * read_page, EEPROM_PAGE_SIZE); + * + * check_if_pages_are_equal(write_page, read_page); + * \endcode + * + * \subsection nvm_quickstart_eeprom_case_workflow Workflow + * + * -# We define where we would like to store our data, and we arbitrarily + * choose page 2 of EEPROM: + * - \code + * #define EXAMPLE_PAGE 2 + * #define EXAMPLE_ADDR EXAMPLE_PAGE * EEPROM_PAGE_SIZE + * \endcode + * -# Define two tables, one which contains the data which we will write, + * and one which we will read the data into: + * - \code + * uint8_t write_page[EEPROM_PAGE_SIZE]; + * uint8_t read_page[EEPROM_PAGE_SIZE]; + * \endcode + * -# Fill the tables with our data, and zero out the read table: + * - \code + * fill_page_with_known_data(write_page); + * fill_page_with_zeroes(read_page); + * \endcode + * - \note These functions are undeclared, you should replace them with + * your own appropriate functions. + * -# We load our page into a temporary EEPROM page buffer: + * - \code + * nvm_eeprom_load_page_to_buffer(write_page); + * \endcode + * - \attention The function used above will not work if memory mapping + * is enabled. + * -# Do an atomic write of the page from buffer into the specified page: + * - \code + * nvm_eeprom_atomic_write_page(EXAMPLE_PAGE); + * \endcode + * - \note The function \ref nvm_eeprom_atomic_write_page() erases the + * page before writing the new one. For non-atomic (split) + * writing without deleting, see \ref nvm_eeprom_split_write_page() + * -# Read the page back into our read_page[] table: + * - \code + * nvm_eeprom_read_buffer(EXAMPLE_ADDR, + * read_page, EEPROM_PAGE_SIZE); + * \endcode + * -# Verify that the page is equal to the one that was written earlier: + * - \code + * check_if_pages_are_equal(write_page, read_page); + * \endcode + * - \note This function is not declared, you should replace it with your + * own appropriate function. + * + * \section xmega_nvm_quickstart_fuse_case Use case 2: Fuses + * + * The NVM driver has functions for reading fuses. + * See \ref nvm_fuse_lock_group. + * + * We would like to check whether the Brown-out Detection level is set to + * 2.1V. This is set by programming the fuses when the chip is connected + * to a suitable programmer. The fuse is a part of FUSEBYTE5. If the BODLVL + * is correct, we turn on LED0. + * + * \section xmega_nvm_quickstart_fuse_case_setup_steps Setup steps + * There are no setup steps required for this use case. + * + * \subsection nvm_quickstart_fuse_case_example_code Example code + * \code + * uint8_t fuse_value; + * fuse_value = nvm_fuses_read(FUSEBYTE5); + * + * if ((fuse_value & NVM_FUSES_BODLVL_gm) == BODLVL_2V1_gc) { + * gpio_set_pin_low(LED0_GPIO); + * } + * \endcode + * + * \subsection nvm_quickstart_fuse_case_workflow Workflow + * + * -# Create a variable to store the fuse contents: + * - \code + * uint8_t fuse_value; + * \endcode + * -# The fuse value we are interested in, BODLVL, is stored in FUSEBYTE5. + * We call the function \ref nvm_fuses_read() to read the fuse into our + * variable: + * - \code + * fuse_value = nvm_fuses_read(FUSEBYTE5); + * \endcode + * -# This ends the reading portion, but we would like to see whether the + * BOD-level is correct, and if it is, light up an LED: + * - \code + * if ((fuse_value & NVM_FUSES_BODLVL_gm) == BODLVL_2V1_gc) { + * gpio_set_pin_low(LED0_GPIO); + * } + * \endcode + * + * \section xmega_nvm_quickstart_signature_case Use case 3: Signature row + * + * The NVM driver has functions for reading the signature row of the device. + * Here we will simply read 16 bytes from the user signature row, assuming + * we need what is stored there. + * + * \section xmega_nvm_quickstart_signature_row_setup_steps Setup steps + * There are no setup steps required for this use case. + * + * \subsection xmega_nvm_quickstart_signature_row_example_code Example code + * + * \code + * #define START_ADDR 0x10 + * #define DATA_LENGTH 16 + * + * uint8_t values[LENGTH]; + * uint8_t i; + * + * for (i = 0; i < DATA_LENGTH; i++) { + * values[i] = nvm_read_user_signature_row(START_ADDR + i); + * } + * \endcode + * + * \subsection nvm_quickstart_signature_case_workflow Workflow + * + * -# Define starting address and length of data segment, and create + * variables needed to store and process the data: + * - \code + * #define START_ADDR 0x10 + * #define DATA_LENGTH 16 + * + * uint8_t values[LENGTH]; + * uint8_t i; + * \endcode + * -# Iterate through the user signature row, and store our desired data: + * - \code + * for (i = 0; i < DATA_LENGTH; i++) { + * values[i] = nvm_read_user_signature_row(START_ADDR + i); + * } + * \endcode + * + */ + +#ifdef __cplusplus +} +#endif + +#endif /* NVM_H */ diff --git a/DSTAT-temp/src/asf/xmega/drivers/nvm/nvm_asm.s b/DSTAT-temp/src/asf/xmega/drivers/nvm/nvm_asm.s new file mode 100644 index 0000000..6d74e08 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/nvm/nvm_asm.s @@ -0,0 +1,197 @@ +/** + * \file + * + * \brief Non Volatile Memory controller driver + * + * Copyright (c) 2010 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include + +#if defined(__GNUC__) +//! Value to write to CCP for access to protected IO registers. +# define CCP_SPM_gc 0x9D + +//! NVM busy flag +# define NVM_NVMBUSY_bp 7 + +//! NVM command for loading flash buffer +# define NVM_CMD_LOAD_FLASH_BUFFER_gc 0x23 +#elif defined(__IAR_SYSTEMS_ASM__) +// All values are defined for IAR +#else +# error Unknown assembler +#endif + +#ifndef __DOXYGEN__ + PUBLIC_FUNCTION(nvm_read_byte) +#if defined(__GNUC__) + lds r20, NVM_CMD ; Store NVM command register + mov ZL, r22 ; Load byte index into low byte of Z. + mov ZH, r23 ; Load high byte into Z. + sts NVM_CMD, r24 ; Load prepared command into NVM Command register. + lpm r24, Z ; Perform an LPM to read out byte + sts NVM_CMD, r20 ; Restore NVM command register +#elif defined(__IAR_SYSTEMS_ASM__) + lds r20, NVM_CMD ; Store NVM command register + mov ZL, r18 ; Load byte index into low byte of Z. + mov ZH, r19 ; Load high byte into Z. + sts NVM_CMD, r16 ; Load prepared command into NVM Command register. + lpm r16, Z ; Perform an LPM to read out byte + sts NVM_CMD, r20 ; Restore NVM command register +#endif + + ret + + END_FUNC(nvm_read_byte) + +// IAR forgets about include files after each module, so need to include again +#if defined(__IAR_SYSTEMS_ASM__) +# include +#endif + + /** + * \brief Perform SPM command + */ + PUBLIC_FUNCTION_SEGMENT(nvm_common_spm, BOOT) + +#if defined(__GNUC__) + /** + * For GCC: + * \param address uint32_t r22:r25 + * \param nvm_cmd uint8_t r20 + */ + in r25, RAMPZ ; Store RAMPZ. Highest address byte is ignored, so using that + out RAMPZ, r24 ; Load R24 into RAMPZ + movw ZL, r22 ; Load R22:R23 into Z. + lds r24, NVM_CMD ; Store NVM command register (r24 is no longer needed) + sts NVM_CMD, r20 ; Load prepared command into NVM Command register. + ldi r23, CCP_SPM_gc ; Prepare Protect SPM signature (r23 is no longer needed) + sts CCP, r23 ; Enable SPM operation (this disables interrupts for 4 cycles). + spm ; Self-program. + sts NVM_CMD, r24 ; Restore NVM command register + out RAMPZ, r25 ; Restore RAMPZ register. +#elif defined(__IAR_SYSTEMS_ASM__) + /** + * For IAR: + * \param address uint32_t r16:r19 + * \param nvm_cmd uint8_t r20 + */ + in r19, RAMPZ ; Store RAMPZ. Highest address byte is ignored, so using that + out RAMPZ, r18 ; Load R18 into RAMPZ + movw ZL, r16 ; Load R16:R17 into Z. + lds r18, NVM_CMD ; Store NVM command register (r18 is no longer needed) + sts NVM_CMD, r20 ; Load prepared command into NVM Command register. + ldi r19, CCP_SPM_gc ; Prepare Protect SPM signature (r19 is no longer needed) + sts CCP, r19 ; Enable SPM operation (this disables interrupts for 4 cycles). + spm ; Self-program. + sts NVM_CMD, r18 ; Restore NVM command register + out RAMPZ, r19 ; Restore RAMPZ register. +#endif + + ret + + END_FUNC(nvm_common_spm) + +// IAR forgets about include files after each module, so need to include again +#if defined(__IAR_SYSTEMS_ASM__) +# include +#endif + + /** + * \brief Load byte to page buffer + * + */ + PUBLIC_FUNCTION_SEGMENT(nvm_flash_load_word_to_buffer, BOOT) + +#if defined(__GNUC__) + /** + * For GCC: + * \param word_addr uint32_t r22:r25 + * \param data uint16_t r20:r21 + */ +wait_nvm: + lds r18, NVM_STATUS + sbrc r18, NVM_NVMBUSY_bp + rjmp wait_nvm + + in r25, RAMPZ ; Store RAMPZ. Highest address byte is ignored, so using that + out RAMPZ, r24 ; Load R24 into RAMPZ + movw ZL, r22 ; Load R22:R23 into Z. + + lds r24, NVM_CMD ; Store NVM command register (r24 is no longer needed) + ldi r18, NVM_CMD_LOAD_FLASH_BUFFER_gc + sts NVM_CMD, r18 ; Load prepared command into NVM Command register. + + movw r0, r20 ; Load R20:R21 into R0:R1 + spm ; Self-program. + + clr r1 ; Clear R1 for GCC _zero_reg_ to function properly. + sts NVM_CMD, r24 ; Restore NVM command register + out RAMPZ, r25 ; Restore RAMPZ register. +#elif defined(__IAR_SYSTEMS_ASM__) + /** + * For IAR: + * \param word_addr uint32_t r16:r19 + * \param data uint16_t r20:r21 + */ +wait_nvm: + lds r19, NVM_STATUS + sbrc r19, NVM_NVMBUSY_bp + rjmp wait_nvm + + in r19, RAMPZ ; Store RAMPZ. Highest byte is ignored, so using that + out RAMPZ, r18 ; Load R18 into RAMPZ + movw ZL, r16 ; Load R16:R17 into Z. + + lds r18, NVM_CMD ; Store NVM command register (r18 is no longer needed) + ldi r17, NVM_CMD_LOAD_FLASH_BUFFER_gc + sts NVM_CMD, r17 ; Load prepared command into NVM Command register. + + movw r0, r20 ; Load R20:R21 into R0:R1 + spm ; Self-program. + + sts NVM_CMD, r18 ; Restore NVM command register + out RAMPZ, r19 ; Restore RAMPZ register. +#endif + + ret + + END_FUNC(nvm_flash_load_word_to_buffer) + + END_FILE() +#endif // __DOXYGEN__ diff --git a/DSTAT-temp/src/asf/xmega/drivers/pmic/pmic.h b/DSTAT-temp/src/asf/xmega/drivers/pmic/pmic.h new file mode 100644 index 0000000..b38e8b1 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/pmic/pmic.h @@ -0,0 +1,349 @@ +/** + * \file + * + * \brief Programmable Multilevel Interrupt Controller driver + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef PMIC_H +#define PMIC_H + +#include +#include + +/** + * \defgroup pmic_group Programmable Multilevel Interrupt Controller + * + * See \ref xmega_pmic_quickstart. + * + * This is a low-level driver implementation for the AVR XMEGA Programmable + * Multilevel Interrupt Controller. + * + * \note If these functions are used in interrupt service routines (ISRs), any + * non-ISR code or ISR code for lower level interrupts must ensure that the + * operations are atomic, i.e., by disabling interrupts during the function + * calls. + * @{ + */ + +/** + * \brief Interrupt level bitmasks + * + * \note These may be OR'ed, e.g., if multiple levels are to be enabled or + * disabled. + */ +enum pmic_level { + PMIC_LVL_LOW = PMIC_LOLVLEN_bm, //!< Low-level interrupts + PMIC_LVL_MEDIUM = PMIC_MEDLVLEN_bm, //!< Medium-level interrupts + PMIC_LVL_HIGH = PMIC_HILVLEN_bm, //!< High-level interrupts + /** + * \brief Non-maskable interrupts + * \note These cannot be enabled nor disabled. + */ + PMIC_LVL_NMI = PMIC_NMIEX_bp, +}; + +//! Interrupt vector locations +enum pmic_vector { + PMIC_VEC_APPLICATION, //!< Application section + PMIC_VEC_BOOT, //!< Boot section + PMIC_NR_OF_VECTORS, //!< Number of interrupt vector locations +}; + +//! Interrupt scheduling schemes +enum pmic_schedule { + PMIC_SCH_FIXED_PRIORITY, //!< Default, fixed priority scheduling + PMIC_SCH_ROUND_ROBIN, //!< Round-robin scheduling + PMIC_NR_OF_SCHEDULES, //!< Number of interrupt scheduling schemes +}; + +/** + * \brief Initialize the PMIC + * + * Enables all interrupt levels, with vectors located in the application section + * and fixed priority scheduling. + */ +static inline void pmic_init(void) +{ + PMIC.CTRL = PMIC_LVL_LOW | PMIC_LVL_MEDIUM | + PMIC_LVL_HIGH; +} + +/** + * \brief Enable interrupts with specified \a level(s). + * + * \param level Interrupt level(s) to enable. + */ +static inline void pmic_enable_level(enum pmic_level level) +{ + Assert((level & PMIC_LVL_NMI)); + + PMIC.CTRL |= level; +} + +/** + * \brief Disable interrupts with specified \a level(s). + * + * \param level Interrupt level(s) to disable. + */ +static inline void pmic_disable_level(enum pmic_level level) +{ + Assert((level & PMIC_LVL_NMI)); + + PMIC.CTRL &= ~level; +} + +/** + * \brief Check if specified interrupt \a level(s) is enabled. + * + * \param level Interrupt level(s) to check. + * + * \return True if interrupt level(s) is enabled. + */ +static inline bool pmic_level_is_enabled(enum pmic_level level) +{ + Assert((level & PMIC_LVL_NMI)); + + return PMIC.CTRL & level; +} + +/** + * \brief Get currently enabled level(s) + * + * \return Bitmask with currently enabled levels. + */ +static inline enum pmic_level pmic_get_enabled_levels(void) +{ + return (enum pmic_level)(PMIC.CTRL & (PMIC_LVL_LOW | PMIC_LVL_MEDIUM + | PMIC_LVL_HIGH)); +} + +/** + * \brief Check if an interrupt level(s) is currently executing. + * + * \param level Interrupt level(s) to check. + * + * \return True if interrupt level(s) is currently executing. + */ +static inline bool pmic_level_is_executing(enum pmic_level level) +{ + return PMIC.STATUS & level; +} + +/** + * \brief Set interrupt scheduling for low-level interrupts. + * + * \param schedule Interrupt scheduling method to set. + * + * \note The low-priority vector, INTPRI, must be set to 0 when round-robin + * scheduling is disabled to return to default interrupt priority order. + */ +static inline void pmic_set_scheduling(enum pmic_schedule schedule) +{ + Assert(schedule < PMIC_NR_OF_SCHEDULES); + + switch (schedule) { + case PMIC_SCH_FIXED_PRIORITY: + PMIC.CTRL &= ~PMIC_RREN_bm; + PMIC.INTPRI = 0; + break; + + case PMIC_SCH_ROUND_ROBIN: + PMIC.CTRL |= PMIC_RREN_bm; + break; + + default: + break; + }; +} + +/** + * \brief Set location of interrupt vectors. + * + * \param vector Location to use for interrupt vectors. + */ +static inline void pmic_set_vector_location(enum pmic_vector vector) +{ + uint8_t ctrl = PMIC.CTRL; + + Assert(vector < PMIC_NR_OF_VECTORS); + + switch (vector) { + case PMIC_VEC_APPLICATION: + ctrl &= ~PMIC_IVSEL_bm; + break; + + case PMIC_VEC_BOOT: + ctrl |= PMIC_IVSEL_bm; + break; + + default: + break; + } + + ccp_write_io((uint8_t*)&PMIC.CTRL, ctrl); +} + +//! @} + +/** + * \page xmega_pmic_quickstart Quick start guide for PMIC driver + * + * This is the quick start guide for the \ref pmic_group "PMIC driver" and + * the closely related \ref interrupt_group "global interrupt driver", with + * step-by-step instructions on how to configure and use the drivers in a + * selection of use cases. + * + * The use cases contain several code fragments. The code fragments in the + * steps for setup can be copied into a custom initialization function, while + * the steps for usage can be copied into, e.g., the main application function. + * + * \section pmic_basic_use_case Basic use case + * In this basic use case, the PMIC is configured for: + * - all interrupt levels enabled + * - round-robin scheduling + * + * This will allow for interrupts from other modules being used. + * + * \section pmic_basic_use_case_setup Setup steps + * + * \subsection pmic_basic_use_case_setup_prereq Prerequisites + * For the setup code of this use case to work, the following must + * be added to the project: + * -# Interrupts for the module requiring the PMIC module have to be + * enabled. + * -# An Interrupt Service Routine (ISR) for a given interrupt vector has to be + * defined, where the interrupt vectors available are defined by toolchain and + * listed in the subsection 'Interrupt Vector Summary' in the data sheet. + * \code + * ISR(interrupt_vector){ + * //Interrupt Service Routine + * } + * \endcode + * + * \subsection pmic_basic_use_case_setup_code Example code + * Add to the initialization code: + * \code + * pmic_init(); + * pmic_set_scheduling(PMIC_SCH_ROUND_ROBIN); + * cpu_irq_enable(); + * \endcode + * + * \subsection pmic_basic_use_case_setup_flow Workflow + * -# call the PMIC driver's own init function to enable all interrupt levels: + * - \code pmic_init(); \endcode + * -# enable round-robin instead of fixed priority interrupt scheduling: + * - \code pmic_set_scheduling(PMIC_SCH_ROUND_ROBIN); \endcode + * -# enable interrupts globally: + * - \code cpu_irq_enable(); \endcode + * - \attention Interrupts will not trigger without this step. + * + * \section pmic_use_cases Advanced use cases + * For more advanced use of the PMIC driver, see the following use cases: + * - \subpage pmic_use_case_1 : atomic operations + */ + +/** + * \page pmic_use_case_1 Use case #1 + * + * In this use case, the PMIC is configured for: + * - all interrupt levels enabled + * + * This will allow for interrupts from other modules being used. + * + * This use case shows how to make an operation which consists of multiple + * instructions uninterruptible, i.e., into an atomic operation. This is often + * necessary if there is a risk that data can be accessed by interrupt handlers + * while other code is accessing it, and at least one of them modifies it. + * + * \section pmic_use_case_1_setup Setup steps + * + * \subsection pmic_basic_use_case_setup_prereq Prerequisites + * For the setup code of this use case to work, the following must + * be added to the project: + * -# Interrupts for the module requiring the PMIC module have to be + * enabled. + * -# An Interrupt Service Routine (ISR) for a given interrupt vector has to be + * defined, where the interrupt vectors available are defined by toolchain and + * listed in the subsection 'Interrupt Vector Summary' in the data sheet. + * \code + * ISR(interrupt_vector){ + * //Interrupt Service Routine + * } + * \endcode + * + * \subsection pmic_use_case_1_setup_code Example code + * Add to application initialization: + * \code + * pmic_init(); + * cpu_irq_enable(); + * \endcode + * + * \subsection pmic_use_case_1_setup_flow Workflow + * -# call the PMIC driver's own init function to enable all interrupt levels: + * - \code pmic_init(); \endcode + * -# set global interrupt enable flag: + * - \code cpu_irq_enable(); \endcode + * + * \section pmic_use_case_1_usage Usage steps + * + * \subsection pmic_use_case_1_usage_code Example code + * \code + * Add to application: + * void atomic_operation(void) + * { + * irqflags_t flags; + * + * flags = cpu_irq_save(); + * + * // Uninterruptible block of code + * + * cpu_irq_restore(flags); + * } + * \endcode + * + * \subsection pmic_use_case_1_usage_flow Workflow + * -# allocate temporary storage for interrupt enable: + * - \code irqflags_t flags; \endcode + * -# clear global interrupt enable flag while saving its previous state: + * - \code flags = cpu_irq_save(); \endcode + * -# restore the previous state of global interrupt flag after operation: + * - \code cpu_irq_restore(flags); \endcode + */ + +#endif /* PMIC_H */ diff --git a/DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.c b/DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.c new file mode 100644 index 0000000..4a347af --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.c @@ -0,0 +1,240 @@ +/** + * \file + * + * \brief AVR XMEGA Real Time Counter driver + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include +#include +#include +#include + +#ifdef CONFIG_RTC_CLOCK_SOURCE +# error CONFIG_RTC_CLOCK_SOURCE is deprecated. Use CONFIG_RTC_SOURCE in \ + conf_clock.h as it is now done in sysclk_init() +#endif + +#ifdef CONFIG_RTC_OVERFLOW_INT_LEVEL +# define RTC_OVERFLOW_INT_LEVEL CONFIG_RTC_OVERFLOW_INT_LEVEL +#else +# define RTC_OVERFLOW_INT_LEVEL RTC_OVFINTLVL_LO_gc +#endif + +#ifdef CONFIG_RTC_COMPARE_INT_LEVEL +# define RTC_COMPARE_INT_LEVEL CONFIG_RTC_COMPARE_INT_LEVEL +#else +# define RTC_COMPARE_INT_LEVEL RTC_COMPINTLVL_LO_gc +#endif + +/** + * \internal + * \brief Driver private struct + */ +struct rtc_data_struct { + //! High value of counter + uint16_t counter_high; + //! High value of alarm time + uint16_t alarm_high; + //! Low value of alarm time + uint16_t alarm_low; + //! Callback function to use on alarm + rtc_callback_t callback; +}; + +/** + * \internal + * \brief Driver private data + */ +struct rtc_data_struct rtc_data; + +/** + * \internal + * \brief Check if RTC is busy synchronizing + */ +static __always_inline bool rtc_is_busy(void) +{ + return RTC.STATUS & RTC_SYNCBUSY_bm; +} + +/** + * \brief Check if pending alarm have triggered + * + * \retval true Alarm have triggered + * \retval false Alarm is pending + */ +__always_inline bool rtc_alarm_has_triggered(void) +{ + return !(RTC.INTCTRL & RTC_COMPARE_INT_LEVEL ); +} + +/** + * \brief Set current time + * + * \param time Time value to set + */ +void rtc_set_time(uint32_t time) +{ + RTC.CTRL = RTC_PRESCALER_OFF_gc; + + while (rtc_is_busy()); + + RTC.CNT = time; + rtc_data.counter_high = time >> 16; + RTC.CTRL = CONFIG_RTC_PRESCALER; +} + +/** + * \brief Get current time + * + * \return Current time value + * + * \note For devices with the errata "RTC Counter value not correctly read + * after sleep", this can return old values shortly after waking up from + * sleep. + * \note Without this errata this function can block for up to 1 RTC + * clock source cycle after waking up from sleep. + */ +uint32_t rtc_get_time(void) +{ + irqflags_t flags; + uint16_t count_high; + uint16_t count_low; + + while (rtc_is_busy()); + + flags = cpu_irq_save(); + count_high = rtc_data.counter_high; + count_low = RTC.CNT; + // Test for possible pending increase of high count value + if ((count_low == 0) && (RTC.INTFLAGS & RTC_OVFIF_bm)) + count_high++; + cpu_irq_restore(flags); + + return ((uint32_t)count_high << 16) | count_low; +} + +/** + * \brief Set alarm time + * + * Will set absolute alarm time that will call the callback specified by \ref + * rtc_set_callback on completion. Or possibly use \ref + * rtc_alarm_has_triggered to check for it. + * + * Any pending alarm will be overwritten with this function. + * + * \param time Absolute time value. See also \ref rtc_min_alarm_time + * \pre Needs interrupts disabled if used from several contexts + */ +void rtc_set_alarm(uint32_t time) +{ + RTC.INTCTRL = RTC_OVERFLOW_INT_LEVEL; + RTC.COMP = time; + rtc_data.alarm_low = time; + rtc_data.alarm_high = time >> 16; + + while (rtc_is_busy()); + + RTC.INTFLAGS = RTC_COMPIF_bm; + RTC.INTCTRL = (uint8_t)RTC_COMPARE_INT_LEVEL + | (uint8_t)RTC_OVERFLOW_INT_LEVEL; +} + +/** + * \brief Set callback to call on alarm + * + * \param callback Callback function pointer + */ +void rtc_set_callback(rtc_callback_t callback) +{ + rtc_data.callback = callback; +} + +/** + * \brief Initialize the RTC + * + * Start up the RTC and start counting from 0 + * + * \note The RTC clock source used by the RTC module should be set up before + * calling this function. + */ +void rtc_init(void) +{ + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_RTC); + RTC.PER = 0xffff; + RTC.CNT = 0; + /* Since overflow interrupt is needed all the time we limit sleep to + * power-save. + */ + sleepmgr_lock_mode(SLEEPMGR_PSAVE); + RTC.INTCTRL = RTC_OVERFLOW_INT_LEVEL; + RTC.CTRL = CONFIG_RTC_PRESCALER; +} + +/** + * \internal + * \brief Overflow interrupt handling high counter + */ +ISR(RTC_OVF_vect) +{ + rtc_data.counter_high++; +} + +/** + * \internal + * \brief Compare interrupt used for alarm + */ +ISR(RTC_COMP_vect) +{ + if (rtc_data.counter_high >= rtc_data.alarm_high) { + RTC.INTCTRL = RTC_OVERFLOW_INT_LEVEL; + if (rtc_data.callback) { + uint32_t count = ((uint32_t)rtc_data.counter_high << 16) + | RTC.CNT; + uint32_t alarm = ((uint32_t)rtc_data.alarm_high << 16) + | rtc_data.alarm_low; + /* Workaround for errata. Count might not be updated + * when waking up from sleep, so in this case use alarm + * time plus one. + */ + if (alarm >= count) + count = alarm + 1; + rtc_data.callback(count); + } + } +} diff --git a/DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.h b/DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.h new file mode 100644 index 0000000..14ca1b6 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/rtc/rtc.h @@ -0,0 +1,290 @@ +/** + * \file + * + * \brief AVR XMEGA Real Time Counter driver definitions + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef DRIVERS_RTC_RTC_H +#define DRIVERS_RTC_RTC_H + +#include +#include + +/** + * \defgroup rtc_group Real Time Counter (RTC) + * + * See \ref xmega_rtc_quickstart. + * + * This is a driver implementation for the XMEGA RTC. + * + * \section rtc_min_alarm_time Minimum allowed alarm time + * + * If current time is close to a time unit roll over, there is a risk to miss + * this when using a value of 0. + * + * A safe use of this can be in an alarm callback. + * + * @{ + */ + +/** + * \def CONFIG_RTC_COMPARE_INT_LEVEL + * \brief Configuration symbol for interrupt level to use on alarm + * + * Possible values: + * - RTC_COMPINTLVL_LO_gc + * - RTC_COMPINTLVL_MED_gc + * - RTC_COMPINTLVL_HI_gc + */ +#ifdef __DOXYGEN__ +# define CONFIG_RTC_COMPARE_INT_LEVEL +#endif + +/** + * \def CONFIG_RTC_OVERFLOW_INT_LEVEL + * \brief Configuration symbol for interrupt level to use on overflow + * + * Possible values: + * - RTC_OVFINTLVL_LO_gc + * - RTC_OVFINTLVL_MED_gc + * - RTC_OVFINTLVL_HI_gc + */ +#ifdef __DOXYGEN__ +# define CONFIG_RTC_OVERFLOW_INT_LEVEL +#endif + +/** + * \def CONFIG_RTC_PRESCALER + * \brief Configuration symbol for prescaler to use + * + * Possible values: + * - RTC_PRESCALER_DIV1_gc + * - RTC_PRESCALER_DIV2_gc + * - RTC_PRESCALER_DIV8_gc + * - RTC_PRESCALER_DIV16_gc + * - RTC_PRESCALER_DIV64_gc + * - RTC_PRESCALER_DIV256_gc + * - RTC_PRESCALER_DIV1024_gc + */ +#ifdef __DOXYGEN__ +# define CONFIG_RTC_PRESCALER +#endif + +/** + * \brief Callback definition for alarm callback + * + * \param time The time of the alarm + */ +typedef void (*rtc_callback_t)(uint32_t time); + +void rtc_set_callback(rtc_callback_t callback); +void rtc_set_time(uint32_t time); +uint32_t rtc_get_time(void); +void rtc_set_alarm(uint32_t time); +bool rtc_alarm_has_triggered(void); + +/** + * \brief Set alarm relative to current time + * + * \param offset Offset to current time. This is minimum value, so the alarm + * might happen at up to one time unit later. See also \ref + * rtc_min_alarm_time + * + * \note For devices with the errata "RTC Counter value not correctly read + * after sleep", this can be unsafe to do shortly after waking up from sleep. + * \note Without this errata this function can block for up to 1 RTC clock + * source cycle after waking up from sleep. + */ +static inline void rtc_set_alarm_relative(uint32_t offset) +{ + rtc_set_alarm(rtc_get_time() + offset); +} + +extern void rtc_init(void); + +//! @} + +/** + * \page xmega_rtc_quickstart Quick start guide for RTC driver + * + * This is the quick start guide for the \ref rtc_group "RTC driver", with + * step-by-step instructions on how to configure and use the drivers in a + * selection of use cases. + * + * The use cases contain several code fragments. The code fragments in the + * steps for setup can be copied into a custom initialization function, while + * the steps for usage can be copied into, e.g., the main application function. + * + * \section rtc_basic_use_case Basic use case + * In this basic use case, the RTC is configured for: + * - Clock source: 1 kHz from internal 32 kHz ULP + * - Prescaling: RTC clock/1024 + * + * \section rtc_basic_use_case_setup Setup steps + * + * \subsection rtc_basic_use_case_setup_code Example code + * Content of conf_rtc.h: + * \code + * #define CONFIG_RTC_PRESCALER RTC_PRESCALER_DIV1024_gc + * \endcode + * Needed in conf_clock.h: + * \code + * #define CONFIG_RTC_SOURCE SYSCLK_RTCSRC_ULP + * \endcode + * Add to the initialization code: + * \code + * sysclk_init(); + * rtc_init(); + * \endcode + * + * \subsection rtc_basic_use_case_setup_flow Workflow + * -# Ensure that conf_rtc.h is present for the driver. + * - \note This configuration file is used by the driver and + * should not be included by the user. + * -# Initialize system clock: + * - \code sysclk_init(); \endcode + * - \note Make sure the define CONFIG_RTC_SOURCE is defined in conf_clock.h + * -# Call RTC driver's own init function to start up the RTC and start + * counting from zero: + * - \code rtc_init(); \endcode + * + * \section rtc_basic_use_case_usage Usage steps + * + * \subsection rtc_basic_use_case_usage_code Example code + * Add to, e.g., main loop in application C-file: + * \code + * rtc_get_time(); + * \endcode + * + * \subsection rtc_basic_use_case_usage_flow Workflow + * -# Get current time of the RTC: + * - \code rtc_get_time(); \endcode + * + * \section rtc_use_cases Advanced use cases + * For more advanced use of the RTC driver, see the following use cases: + * - \subpage rtc_use_case_1 : + */ + +/** + * \page rtc_use_case_1 Use case #1 + * + * In this use case, the RTC is configured for: + * - Clock source: 1 kHz from internal 32 kHz ULP + * - Prescaling: RTC clock/1024 + * + * This use case shows how to set an alarm for the RTC. + * + * \section rtc_use_case_1_setup Setup steps + * + * \subsection rtc_basic_use_case_setup_prereq Prerequisites + * For the setup code of this use case to work, the following must + * be added to the project: + * -# PMIC for interrupt handling. + * -# Sleep Manager. + * -# A \ref rtc_callback_t "callback" function, called alarm, that + * reschedules the alarm must be provided by the user: + * \code + * static void alarm(uint32_t time) + * { + * rtc_set_alarm(time); + * } + * \endcode + * + * \subsection rtc_use_case_1_setup_code Example code + * Content of conf_rtc.h: + * \code + * #define CONFIG_RTC_PRESCALER RTC_PRESCALER_DIV1024_gc + * \endcode + * Needed in conf_clock.h: + * \code + * #define CONFIG_RTC_SOURCE SYSCLK_RTCSRC_ULP + * \endcode + * Add to application initialization: + * \code + * pmic_init(); + * sysclk_init(); + * sleepmgr_init(); + * rtc_init(); + * rtc_set_callback(alarm); + * cpu_irq_enable(); + * \endcode + * + * \subsection rtc_use_case_1_setup_flow Workflow + * -# Ensure that conf_rtc.h is present for the driver. + * - \note This configuration file is used by the driver and + * should not be included by the user. + * -# Call the init function of the PMIC driver to enable all interrupt levels: + * - \code pmic_init(); \endcode + * -# Initialize system clock: + * - \code sysclk_init(); \endcode + * - \note Make sure the define CONFIG_RTC_SOURCE is defined in conf_clock.h + * -# Call the init function of the sleep manager driver to be able to sleep + * waiting for alarm: + * - \code sleepmgr_init(); \endcode + * -# Call RTC driver's own init function to start up the RTC and start + * counting from zero: + * - \code rtc_init(); \endcode + * -# Set callback function to call on alarm: + * - \code rtc_set_callback(alarm); \endcode + * - \note The callback function alarm must be defined by the user. + * -# Enable interrupts globally: + * - \code cpu_irq_enable(); \endcode + * + * \section rtc_use_case_1_usage Usage steps + * + * \subsection rtc_use_case_1_usage_code Example code + * \code + * rtc_set_alarm_relative(0); + * while (true) { + * sleepmgr_enter_sleep(); + * } + * \endcode + * + * \subsection rtc_use_case_1_usage_flow Workflow + * -# Set the alarm to trigger on next time unit roll over: + * - \code rtc_set_alarm_relative(0); \endcode + * -# Sleep between each triggered alarm: + * - \code + * while (true) { + * sleepmgr_enter_sleep(); + * } + * \endcode + */ + +#endif /* RTC_H */ diff --git a/DSTAT-temp/src/asf/xmega/drivers/sleep/sleep.h b/DSTAT-temp/src/asf/xmega/drivers/sleep/sleep.h new file mode 100644 index 0000000..7597d5f --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/sleep/sleep.h @@ -0,0 +1,166 @@ +/** + * \file + * + * \brief Sleep controller driver + * + * Copyright (c) 2010 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef SLEEP_H +#define SLEEP_H + +#include + +/** + * \defgroup sleep_group Sleep controller driver + * + * This is a low-level driver implementation for the AVR XMEGA sleep controller. + * + * \note To minimize the code overhead, these functions do not feature + * interrupt-protected access since they are likely to be called inside + * interrupt handlers or in applications where such protection is not + * necessary. If such protection is needed, it must be ensured by the calling + * code. + * + * \section xmega_sleep_quickstart_section Quick Start Guide + * See \ref xmega_sleep_quickstart + * @{ + */ + +#if defined(__ICCAVR__) || defined(__DOXYGEN__) +# include +//! Macro for issuing the sleep instruction. +# define sleep_enter() __sleep() + +/** + * \brief Enable sleep + */ +static inline void sleep_enable(void) +{ + SLEEP.CTRL |= SLEEP_SEN_bm; +} + +/** + * \brief Disable sleep + */ +static inline void sleep_disable(void) +{ + SLEEP.CTRL &= ~SLEEP_SEN_bm; +} + +#elif defined(__GNUC__) +# include +# define sleep_enter() sleep_cpu() + +#else +# error Unsupported compiler. +#endif + +/** + * \brief Set new sleep mode + * + * \param mode Sleep mode, from the device IO header file. + */ +static inline void sleep_set_mode(enum SLEEP_SMODE_enum mode) +{ + SLEEP.CTRL = mode | (SLEEP.CTRL & ~SLEEP_SMODE_gm); +} + +//! @} + +/** + * \page xmega_sleep_quickstart Quick Start Guide for the XMEGA Sleep Driver + * + * This is the quick start guide for the \ref sleep_group "Sleep Driver", with + * step-by-step instructions on how to configure and use the driver for a + * specific use case. + * + * The section described below can be copied into, e.g. the main application + * loop or any other function that will need to control and execute different + * sleep modes on the device. + * + * \section xmega_sleep_quickstart_basic Basic usage of the sleep driver + * This use case will prepare the device to enter the Power Down sleep mode and + * then enter the sleep mode. After waking up it will disable sleep. + * + * \section xmega_sleep_basic_usage Usage steps + * \subsection xmega_sleep_basic_usage_code Example code + * Add to, e.g., the main loop in the application C-file: + * \code + * sleep_set_mode(SLEEP_SMODE_PDOWN_gc); + * sleep_enable(); + * sleep_enter(); + * sleep_disable(); + * \endcode + * + * \subsection xmega_sleep_basic_usage Workflow + * -# Set what sleep mode to use, the different sleep modes can be found in the + * device header file under the enum definition SLEEP_SMODE_enum: + * - \code sleep_set_mode(SLEEP_SMODE_PDOWN_gc); \endcode + * -# Enable that the device are allowed to go to sleep: + * - \code sleep_enable(); \endcode + * - \note This function has to be called in order for the device to go to + * sleep. This is a safety feature to stop the device to go to sleep + * unintentionally, even though it is possible to have this enabled at all times + * it is recommended to enable sleep mode only when you intend to go to sleep + * within a few clock cycles. + * -# Enter sleep mode: + * - \code sleep_enter(); \endcode + * - \attention Make sure to enable global interrupt and the interrupt you + * plan to use as wake-up source for your device, do also pay special + * attention to what wake-up sources are available for the different sleep + * modes. Failing to enable interrupts may result in indefinite sleep until + * power is cycled! + * -# When the device is woken from sleep it will execute the interrupt handler + * related to the wakeup-source (interrupt source) and continue on the next line + * of code after the \ref sleep_enter() call. Make sure to disable sleep when + * waking up. + * - \code sleep_disable(); \endcode + * + * \subsection xmega_sleep_basic_sleep_modes Sleep Modes + * Possible sleep modes depend on the device that is used. Please refer to the + * device datasheet and header file to find these definitions. + * + * As an example the ATxmega32A4U device has the following sleep modes: + * - Idle sleep: SLEEP_SMODE_IDLE_gc + * - Power Down: SLEEP_SMODE_PDOWN_gc + * - Power Save: SLEEP_SMODE_PSAVE_gc + * - Standby: SLEEP_SMODE_STDBY_gc + * - Extended standby: SLEEP_SMODE_ESTDBY_gc + */ + +#endif /* SLEEP_H */ diff --git a/DSTAT-temp/src/asf/xmega/drivers/tc/tc.c b/DSTAT-temp/src/asf/xmega/drivers/tc/tc.c new file mode 100644 index 0000000..95cefdb --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/tc/tc.c @@ -0,0 +1,1078 @@ +/** + * \file + * + * \brief AVR XMEGA TC Driver + * + * Copyright (c) 2010 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include + +#include "interrupt.h" +#include "compiler.h" +#include "parts.h" + +#include "tc.h" +#include "sysclk.h" +#include "sleepmgr.h" +#include "status_codes.h" + +#if defined(TCC0) || defined(__DOXYGEN__) +//! \internal Local storage of Timer Counter TCC0 interrupt callback function +static tc_callback_t tc_tcc0_ovf_callback; +static tc_callback_t tc_tcc0_err_callback; +static tc_callback_t tc_tcc0_cca_callback; +static tc_callback_t tc_tcc0_ccb_callback; +static tc_callback_t tc_tcc0_ccc_callback; +static tc_callback_t tc_tcc0_ccd_callback; + + +/** + * \internal + * \brief Interrupt handler for Timer Counter C0 overflow + * + * This function will handle interrupt on Timer Counter CO overflow and + * call the callback function. + */ +ISR(TCC0_OVF_vect) +{ + if (tc_tcc0_ovf_callback) { + tc_tcc0_ovf_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter C0 error + * + * This function will handle interrupt on Timer Counter CO error and + * call the callback function. + */ +ISR(TCC0_ERR_vect) +{ + if (tc_tcc0_err_callback) { + tc_tcc0_err_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter C0 Compare/CaptureA + * + * This function will handle interrupt on Timer Counter CO Compare/CaptureA and + * call the callback function. + */ +ISR(TCC0_CCA_vect) +{ + if (tc_tcc0_cca_callback) { + tc_tcc0_cca_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter C0 Compare/CaptureB + * + * This function will handle interrupt on Timer Counter CO Compare/CaptureB and + * call the callback function. + */ +ISR(TCC0_CCB_vect) +{ + if (tc_tcc0_ccb_callback) { + tc_tcc0_ccb_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter C0 Compare/CaptureC + * + * This function will handle interrupt on Timer Counter CO Compare/CaptureC and + * call the callback function. + */ +ISR(TCC0_CCC_vect) +{ + if (tc_tcc0_ccc_callback) { + tc_tcc0_ccc_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter C0 Compare/CaptureD + * + * This function will handle interrupt on Timer Counter CO Compare/CaptureD and + * call the callback function. + */ +ISR(TCC0_CCD_vect) +{ + if (tc_tcc0_ccd_callback) { + tc_tcc0_ccd_callback(); + } +} + +#endif + +#if defined(TCC1) || defined(__DOXYGEN__) +//! \internal Local storage of Timer Counter TCC1 interrupt callback function +static tc_callback_t tc_tcc1_ovf_callback; +static tc_callback_t tc_tcc1_err_callback; +static tc_callback_t tc_tcc1_cca_callback; +static tc_callback_t tc_tcc1_ccb_callback; + +/** + * \internal + * \brief Interrupt handler for Timer Counter C1 overflow + * + * This function will handle interrupt on Timer Counter C1 overflow and + * call the callback function. + */ +ISR(TCC1_OVF_vect) +{ + if (tc_tcc1_ovf_callback) { + tc_tcc1_ovf_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter C1 error + * + * This function will handle interrupt on Timer Counter C1 error and + * call the callback function. + */ +ISR(TCC1_ERR_vect) +{ + if (tc_tcc1_err_callback) { + tc_tcc1_err_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter C1 Compare/CaptureA + * + * This function will handle interrupt on Timer Counter C1 Compare/CaptureA and + * call the callback function. + */ +ISR(TCC1_CCA_vect) +{ + if (tc_tcc1_cca_callback) { + tc_tcc1_cca_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter C1 Compare/CaptureB + * + * This function will handle interrupt on Timer Counter C1 Compare/CaptureB and + * call the callback function. + */ +ISR(TCC1_CCB_vect) +{ + if (tc_tcc1_ccb_callback) { + tc_tcc1_ccb_callback(); + } +} + +#endif + +#if defined(TCD0) || defined(__DOXYGEN__) +//! \internal Local storage of Timer Counter TCD0 interrupt callback function +static tc_callback_t tc_tcd0_ovf_callback; +static tc_callback_t tc_tcd0_err_callback; +static tc_callback_t tc_tcd0_cca_callback; +static tc_callback_t tc_tcd0_ccb_callback; +static tc_callback_t tc_tcd0_ccc_callback; +static tc_callback_t tc_tcd0_ccd_callback; + + +/** + * \internal + * \brief Interrupt handler for Timer Counter D0 overflow + * + * This function will handle interrupt on Timer Counter D0 overflow and + * call the callback function. + */ +ISR(TCD0_OVF_vect) +{ + if (tc_tcd0_ovf_callback) { + tc_tcd0_ovf_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter D0 error + * + * This function will handle interrupt on Timer Counter D0 error and + * call the callback function. + */ +ISR(TCD0_ERR_vect) +{ + if (tc_tcd0_err_callback) { + tc_tcd0_err_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter D0 Compare/CaptureA + * + * This function will handle interrupt on Timer Counter D0 Compare/CaptureA and + * call the callback function. + */ +ISR(TCD0_CCA_vect) +{ + if (tc_tcd0_cca_callback) { + tc_tcd0_cca_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter D0 Compare/CaptureB + * + * This function will handle interrupt on Timer Counter D0 Compare/CaptureB and + * call the callback function. + */ +ISR(TCD0_CCB_vect) +{ + if (tc_tcd0_ccb_callback) { + tc_tcd0_ccb_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter D0 Compare/CaptureC + * + * This function will handle interrupt on Timer Counter D0 Compare/CaptureC and + * call the callback function. + */ +ISR(TCD0_CCC_vect) +{ + if (tc_tcd0_ccc_callback) { + tc_tcd0_ccc_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter D0 Compare/CaptureD + * + * This function will handle interrupt on Timer Counter D0 Compare/CaptureD and + * call the callback function. + */ +ISR(TCD0_CCD_vect) +{ + if (tc_tcd0_ccd_callback) { + tc_tcd0_ccd_callback(); + } +} + +#endif + +#if defined(TCD1) || defined(__DOXYGEN__) +//! \internal Local storage of Timer Counter TCD1 interrupt callback function +static tc_callback_t tc_tcd1_ovf_callback; +static tc_callback_t tc_tcd1_err_callback; +static tc_callback_t tc_tcd1_cca_callback; +static tc_callback_t tc_tcd1_ccb_callback; + +/** + * \internal + * \brief Interrupt handler for Timer Counter D1 overflow + * + * This function will handle interrupt on Timer Counter D1 overflow and + * call the callback function. + */ +ISR(TCD1_OVF_vect) +{ + if (tc_tcd1_ovf_callback) { + tc_tcd1_ovf_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter D1 error + * + * This function will handle interrupt on Timer Counter D1 error and + * call the callback function. + */ +ISR(TCD1_ERR_vect) +{ + if (tc_tcd1_err_callback) { + tc_tcd1_err_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter D1 Compare/CaptureA + * + * This function will handle interrupt on Timer Counter D1 Compare/CaptureA and + * call the callback function. + */ +ISR(TCD1_CCA_vect) +{ + if (tc_tcd1_cca_callback) { + tc_tcd1_cca_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter D1 Compare/CaptureB + * + * This function will handle interrupt on Timer Counter D1 Compare/CaptureB and + * call the callback function. + */ +ISR(TCD1_CCB_vect) +{ + if (tc_tcd1_ccb_callback) { + tc_tcd1_ccb_callback(); + } +} + +#endif + + +#if defined(TCE0) || defined(__DOXYGEN__) +//! \internal Local storage of Timer Counter TCE0 interrupt callback function +static tc_callback_t tc_tce0_ovf_callback; +static tc_callback_t tc_tce0_err_callback; +static tc_callback_t tc_tce0_cca_callback; +static tc_callback_t tc_tce0_ccb_callback; +static tc_callback_t tc_tce0_ccc_callback; +static tc_callback_t tc_tce0_ccd_callback; + + +/** + * \internal + * \brief Interrupt handler for Timer Counter E0 overflow + * + * This function will handle interrupt on Timer Counter E0 overflow and + * call the callback function. + */ +ISR(TCE0_OVF_vect) +{ + if (tc_tce0_ovf_callback) { + tc_tce0_ovf_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter E0 error + * + * This function will handle interrupt on Timer Counter E0 error and + * call the callback function. + */ +ISR(TCE0_ERR_vect) +{ + if (tc_tce0_err_callback) { + tc_tce0_err_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter E0 Compare/CaptureA + * + * This function will handle interrupt on Timer Counter E0 Compare/CaptureA and + * call the callback function. + */ +ISR(TCE0_CCA_vect) +{ + if (tc_tce0_cca_callback) { + tc_tce0_cca_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter E0 Compare/CaptureB + * + * This function will handle interrupt on Timer Counter E0 Compare/CaptureB and + * call the callback function. + */ +ISR(TCE0_CCB_vect) +{ + if (tc_tce0_ccb_callback) { + tc_tce0_ccb_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter E0 Compare/CaptureC + * + * This function will handle interrupt on Timer Counter E0 Compare/CaptureC and + * call the callback function. + */ +ISR(TCE0_CCC_vect) +{ + if (tc_tce0_ccc_callback) { + tc_tce0_ccc_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter E0 Compare/CaptureD + * + * This function will handle interrupt on Timer Counter E0 Compare/CaptureD and + * call the callback function. + */ +ISR(TCE0_CCD_vect) +{ + if (tc_tce0_ccd_callback) { + tc_tce0_ccd_callback(); + } +} + +#endif + +#if defined(TCE1) || defined(__DOXYGEN__) +//! \internal Local storage of Timer Counter TCE1 interrupt callback function +static tc_callback_t tc_tce1_ovf_callback; +static tc_callback_t tc_tce1_err_callback; +static tc_callback_t tc_tce1_cca_callback; +static tc_callback_t tc_tce1_ccb_callback; + +/** + * \internal + * \brief Interrupt handler for Timer Counter E1 overflow + * + * This function will handle interrupt on Timer Counter E1 overflow and + * call the callback function. + */ +ISR(TCE1_OVF_vect) +{ + if (tc_tce1_ovf_callback) { + tc_tce1_ovf_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter E1 error + * + * This function will handle interrupt on Timer Counter E1 error and + * call the callback function. + */ +ISR(TCE1_ERR_vect) +{ + if (tc_tce1_err_callback) { + tc_tce1_err_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter E1 Compare/CaptureA + * + * This function will handle interrupt on Timer Counter E1 Compare/CaptureA and + * call the callback function. + */ +ISR(TCE1_CCA_vect) +{ + if (tc_tce1_cca_callback) { + tc_tce1_cca_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter E1 Compare/CaptureB + * + * This function will handle interrupt on Timer Counter E1 Compare/CaptureB and + * call the callback function. + */ +ISR(TCE1_CCB_vect) +{ + if (tc_tce1_ccb_callback) { + tc_tce1_ccb_callback(); + } +} + +#endif + +#if defined(TCF0) || defined(__DOXYGEN__) +//! \internal Local storage of Timer Counter TCF0 interrupt callback function +static tc_callback_t tc_tcf0_ovf_callback; +static tc_callback_t tc_tcf0_err_callback; +static tc_callback_t tc_tcf0_cca_callback; +static tc_callback_t tc_tcf0_ccb_callback; +static tc_callback_t tc_tcf0_ccc_callback; +static tc_callback_t tc_tcf0_ccd_callback; + + +/** + * \internal + * \brief Interrupt handler for Timer Counter E0 overflow + * + * This function will handle interrupt on Timer Counter F0 overflow and + * call the callback function. + */ +ISR(TCF0_OVF_vect) +{ + if (tc_tcf0_ovf_callback) { + tc_tcf0_ovf_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter F0 error + * + * This function will handle interrupt on Timer Counter F0 error and + * call the callback function. + */ +ISR(TCF0_ERR_vect) +{ + if (tc_tcf0_err_callback) { + tc_tcf0_err_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter F0 Compare/CaptureA + * + * This function will handle interrupt on Timer Counter F0 Compare/CaptureA and + * call the callback function. + */ +ISR(TCF0_CCA_vect) +{ + if (tc_tcf0_cca_callback) { + tc_tcf0_cca_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter F0 Compare/CaptureB + * + * This function will handle interrupt on Timer Counter F0 Compare/CaptureB and + * call the callback function. + */ +ISR(TCF0_CCB_vect) +{ + if (tc_tcf0_ccb_callback) { + tc_tcf0_ccb_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter F0 Compare/CaptureC + * + * This function will handle interrupt on Timer Counter F0 Compare/CaptureC and + * call the callback function. + */ +ISR(TCF0_CCC_vect) +{ + if (tc_tcf0_ccc_callback) { + tc_tcf0_ccc_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter F0 Compare/CaptureD + * + * This function will handle interrupt on Timer Counter F0 Compare/CaptureD and + * call the callback function. + */ +ISR(TCF0_CCD_vect) +{ + if (tc_tcf0_ccd_callback) { + tc_tcf0_ccd_callback(); + } +} + +#endif + +#if defined(TCF1) || defined(__DOXYGEN__) +//! \internal Local storage of Timer Counter TCF1 interrupt callback function +static tc_callback_t tc_tcf1_ovf_callback; +static tc_callback_t tc_tcf1_err_callback; +static tc_callback_t tc_tcf1_cca_callback; +static tc_callback_t tc_tcf1_ccb_callback; + +/** + * \internal + * \brief Interrupt handler for Timer Counter F1 overflow + * + * This function will handle interrupt on Timer Counter F1 overflow and + * call the callback function. + */ +ISR(TCF1_OVF_vect) +{ + if (tc_tcf1_ovf_callback) { + tc_tcf1_ovf_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter F1 error + * + * This function will handle interrupt on Timer Counter F1 error and + * call the callback function. + */ +ISR(TCF1_ERR_vect) +{ + if (tc_tcf1_err_callback) { + tc_tcf1_err_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter F1 Compare/CaptureA + * + * This function will handle interrupt on Timer Counter F1 Compare/CaptureA and + * call the callback function. + */ +ISR(TCF1_CCA_vect) +{ + if (tc_tcf1_cca_callback) { + tc_tcf1_cca_callback(); + } +} + +/** + * \internal + * \brief Interrupt handler for Timer Counter F1 Compare/CaptureB + * + * This function will handle interrupt on Timer Counter F1 Compare/CaptureB and + * call the callback function. + */ +ISR(TCF1_CCB_vect) +{ + if (tc_tcf1_ccb_callback) { + tc_tcf1_ccb_callback(); + } +} + +#endif + +/** + * \brief Enable TC + * + * Enables the TC. + * + * \param tc Pointer to TC module + * + * \note + * unmask TC clock (sysclk), but does not configure the TC clock source. + */ +void tc_enable(volatile void *tc) +{ + irqflags_t iflags = cpu_irq_save(); + +#ifdef TCC0 + if ((uintptr_t) tc == (uintptr_t) & TCC0) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC0); + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_HIRES); + } else +#endif +#ifdef TCC1 + if ((uintptr_t) tc == (uintptr_t) & TCC1) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC1); + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_HIRES); + } else +#endif +#ifdef TCD0 + if ((uintptr_t) tc == (uintptr_t) & TCD0) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_TC0); + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_HIRES); + } else +#endif +#ifdef TCD1 + if ((uintptr_t) tc == (uintptr_t) & TCD1) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_TC1); + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_HIRES); + } else +#endif +#ifdef TCE0 + if ((uintptr_t) tc == (uintptr_t) & TCE0) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_TC0); + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_HIRES); + } else +#endif +#ifdef TCE1 + if ((uintptr_t) tc == (uintptr_t) & TCE1) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_TC1); + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_HIRES); + } else +#endif +#ifdef TCF0 + if ((uintptr_t) tc == (uintptr_t) & TCF0) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_TC0); + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_HIRES); + } else +#endif +#ifdef TCF1 + if ((uintptr_t) tc == (uintptr_t) & TCF1) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_TC1); + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_HIRES); + } else +#endif + { + cpu_irq_restore(iflags); + return; + } + sleepmgr_lock_mode(SLEEPMGR_IDLE); + cpu_irq_restore(iflags); +} + + +/** + * \brief Disable TC + * + * Disables the TC. + * + * \param tc Pointer to TC module + * + * \note + * mask TC clock (sysclk). + */ +void tc_disable(volatile void *tc) +{ + irqflags_t iflags = cpu_irq_save(); + + sleepmgr_unlock_mode(SLEEPMGR_IDLE); + +#ifdef TCC0 + if ((uintptr_t) tc == (uintptr_t) & TCC0) { + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_TC0); + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_HIRES); + } else +#endif +#ifdef TCC1 + if ((uintptr_t) tc == (uintptr_t) & TCC1) { + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_TC1); + sysclk_disable_module(SYSCLK_PORT_C, SYSCLK_HIRES); + } else +#endif +#ifdef TCD0 + if ((uintptr_t) tc == (uintptr_t) & TCD0) { + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_TC0); + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_HIRES); + } else +#endif +#ifdef TCD1 + if ((uintptr_t) tc == (uintptr_t) & TCD1) { + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_TC1); + sysclk_disable_module(SYSCLK_PORT_D, SYSCLK_HIRES); + } else +#endif +#ifdef TCE0 + if ((uintptr_t) tc == (uintptr_t) & TCE0) { + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_TC0); + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_HIRES); + } else +#endif +#ifdef TCE1 + if ((uintptr_t) tc == (uintptr_t) & TCE1) { + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_TC1); + sysclk_disable_module(SYSCLK_PORT_E, SYSCLK_HIRES); + } else +#endif +#ifdef TCF0 + if ((uintptr_t) tc == (uintptr_t) & TCF0) { + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_TC0); + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_HIRES); + } else +#endif +#ifdef TCF1 + if ((uintptr_t) tc == (uintptr_t) & TCF1) { + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_TC1); + sysclk_disable_module(SYSCLK_PORT_F, SYSCLK_HIRES); + } else +#endif + { + cpu_irq_restore(iflags); + return; + } + cpu_irq_restore(iflags); +} + +void tc_set_overflow_interrupt_callback(volatile void *tc, + tc_callback_t callback) +{ +#ifdef TCC0 + if ((uintptr_t) tc == (uintptr_t) & TCC0) { + tc_tcc0_ovf_callback = callback; + } else +#endif +#ifdef TCC1 + if ((uintptr_t) tc == (uintptr_t) & TCC1) { + tc_tcc1_ovf_callback = callback; + } else +#endif +#ifdef TCD0 + if ((uintptr_t) tc == (uintptr_t) & TCD0) { + tc_tcd0_ovf_callback = callback; + } else +#endif +#ifdef TCD1 + if ((uintptr_t) tc == (uintptr_t) & TCD1) { + tc_tcd1_ovf_callback = callback; + } else +#endif +#ifdef TCE0 + if ((uintptr_t) tc == (uintptr_t) & TCE0) { + tc_tce0_ovf_callback = callback; + } else +#endif +#ifdef TCE1 + if ((uintptr_t) tc == (uintptr_t) & TCE1) { + tc_tce1_ovf_callback = callback; + } else +#endif +#ifdef TCF0 + if ((uintptr_t) tc == (uintptr_t) & TCF0) { + tc_tcf0_ovf_callback = callback; + } else +#endif +#ifdef TCF1 + if ((uintptr_t) tc == (uintptr_t) & TCF1) { + tc_tcf1_ovf_callback = callback; + } else +#endif + {} +} + +void tc_set_error_interrupt_callback(volatile void *tc, tc_callback_t callback) +{ +#ifdef TCC0 + if ((uintptr_t) tc == (uintptr_t) & TCC0) { + tc_tcc0_err_callback = callback; + } else +#endif +#ifdef TCC1 + if ((uintptr_t) tc == (uintptr_t) & TCC1) { + tc_tcc1_err_callback = callback; + } else +#endif +#ifdef TCD0 + if ((uintptr_t) tc == (uintptr_t) & TCD0) { + tc_tcd0_err_callback = callback; + } else +#endif +#ifdef TCD1 + if ((uintptr_t) tc == (uintptr_t) & TCD1) { + tc_tcd1_err_callback = callback; + } else +#endif +#ifdef TCE0 + if ((uintptr_t) tc == (uintptr_t) & TCE0) { + tc_tce0_err_callback = callback; + } else +#endif +#ifdef TCE1 + if ((uintptr_t) tc == (uintptr_t) & TCE1) { + tc_tce1_err_callback = callback; + } else +#endif +#ifdef TCF0 + if ((uintptr_t) tc == (uintptr_t) & TCF0) { + tc_tcf0_err_callback = callback; + } else +#endif +#ifdef TCF1 + if ((uintptr_t) tc == (uintptr_t) & TCF1) { + tc_tcf1_err_callback = callback; + } else +#endif + {} +} + +void tc_set_cca_interrupt_callback(volatile void *tc, tc_callback_t callback) +{ +#ifdef TCC0 + if ((uintptr_t) tc == (uintptr_t) & TCC0) { + tc_tcc0_cca_callback = callback; + } else +#endif +#ifdef TCC1 + if ((uintptr_t) tc == (uintptr_t) & TCC1) { + tc_tcc1_cca_callback = callback; + } else +#endif +#ifdef TCD0 + if ((uintptr_t) tc == (uintptr_t) & TCD0) { + tc_tcd0_cca_callback = callback; + } else +#endif +#ifdef TCD1 + if ((uintptr_t) tc == (uintptr_t) & TCD1) { + tc_tcd1_cca_callback = callback; + } else +#endif +#ifdef TCE0 + if ((uintptr_t) tc == (uintptr_t) & TCE0) { + tc_tce0_cca_callback = callback; + } else +#endif +#ifdef TCE1 + if ((uintptr_t) tc == (uintptr_t) & TCE1) { + tc_tce1_cca_callback = callback; + } else +#endif +#ifdef TCF0 + if ((uintptr_t) tc == (uintptr_t) & TCF0) { + tc_tcf0_cca_callback = callback; + } else +#endif +#ifdef TCF1 + if ((uintptr_t) tc == (uintptr_t) & TCF1) { + tc_tcf1_cca_callback = callback; + } else +#endif + {} +} + +void tc_set_ccb_interrupt_callback(volatile void *tc, tc_callback_t callback) +{ +#ifdef TCC0 + if ((uintptr_t) tc == (uintptr_t) & TCC0) { + tc_tcc0_ccb_callback = callback; + } else +#endif +#ifdef TCC1 + if ((uintptr_t) tc == (uintptr_t) & TCC1) { + tc_tcc1_ccb_callback = callback; + } else +#endif +#ifdef TCD0 + if ((uintptr_t) tc == (uintptr_t) & TCD0) { + tc_tcd0_ccb_callback = callback; + } else +#endif +#ifdef TCD1 + if ((uintptr_t) tc == (uintptr_t) & TCD1) { + tc_tcd1_ccb_callback = callback; + } else +#endif +#ifdef TCE0 + if ((uintptr_t) tc == (uintptr_t) & TCE0) { + tc_tce0_ccb_callback = callback; + } else +#endif +#ifdef TCE1 + if ((uintptr_t) tc == (uintptr_t) & TCE1) { + tc_tce1_ccb_callback = callback; + } else +#endif +#ifdef TCF0 + if ((uintptr_t) tc == (uintptr_t) & TCF0) { + tc_tcf0_ccb_callback = callback; + } else +#endif +#ifdef TCF1 + if ((uintptr_t) tc == (uintptr_t) & TCF1) { + tc_tcf1_ccb_callback = callback; + } else +#endif + {} +} + +void tc_set_ccc_interrupt_callback(volatile void *tc, tc_callback_t callback) +{ +#ifdef TCC0 + if ((uintptr_t) tc == (uintptr_t) & TCC0) { + tc_tcc0_ccc_callback = callback; + } else +#endif + +#ifdef TCD0 + if ((uintptr_t) tc == (uintptr_t) & TCD0) { + tc_tcd0_ccc_callback = callback; + } else +#endif + +#ifdef TCE0 + if ((uintptr_t) tc == (uintptr_t) & TCE0) { + tc_tce0_ccc_callback = callback; + } else +#endif + +#ifdef TCF0 + if ((uintptr_t) tc == (uintptr_t) & TCF0) { + tc_tcf0_ccc_callback = callback; + } else +#endif + {} + +} + + +void tc_set_ccd_interrupt_callback(volatile void *tc, tc_callback_t callback) +{ +#ifdef TCC0 + if ((uintptr_t) tc == (uintptr_t) & TCC0) { + tc_tcc0_ccd_callback = callback; + } else +#endif + +#ifdef TCD0 + if ((uintptr_t) tc == (uintptr_t) & TCD0) { + tc_tcd0_ccd_callback = callback; + } else +#endif + +#ifdef TCE0 + if ((uintptr_t) tc == (uintptr_t) & TCE0) { + tc_tce0_ccd_callback = callback; + } else +#endif + +#ifdef TCF0 + if ((uintptr_t) tc == (uintptr_t) & TCF0) { + tc_tcf0_ccd_callback = callback; + } else +#endif + {} +} diff --git a/DSTAT-temp/src/asf/xmega/drivers/tc/tc.h b/DSTAT-temp/src/asf/xmega/drivers/tc/tc.h new file mode 100644 index 0000000..a770e94 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/tc/tc.h @@ -0,0 +1,1612 @@ +/** + * \file + * + * \brief AVR XMEGA Timer Counter (TC) driver + * + * Copyright (c) 2010-2011 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef TC_H +#define TC_H + +#include +#include +#include "status_codes.h" +#include "pmic.h" +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + * \defgroup tc_group Timer Counter (TC) + * + * See \ref xmega_tc_quickstart + * + * This is a driver for the AVR XMEGA Timer Counter (TC). It provides functions + * for enabling, disabling and configuring the TC modules. + * + * \section dependencies Dependencies + * This driver depends on the following modules: + * - \ref sysclk_group for peripheral clock control. + * - \ref sleepmgr_group for setting allowed sleep mode. + * - \ref interrupt_group for ISR definition and disabling interrupts during + * critical code sections. + * @{ + */ + + + +/** + * \brief Interrupt event callback function type + * + * The interrupt handler can be configured to do a function callback, + * the callback function must match the tc_callback_t type. + * + */ +typedef void (*tc_callback_t) (void); + +//! Timer Counter Capture Compare Channel index +enum tc_cc_channel_t { + //! Channel A + TC_CCA = 1, + //! Channel B + TC_CCB = 2, + //! Channel C + TC_CCC = 3, + //! Channel D + TC_CCD = 4, +}; + +//! Timer Counter Capture Compare Channel index +enum tc_cc_channel_mask_enable_t { + //! Channel A Enable mask + TC_CCAEN = TC0_CCAEN_bm, + //! Channel B Enable mask + TC_CCBEN = TC0_CCBEN_bm, + //! Channel C Enable mask + TC_CCCEN = TC0_CCCEN_bm, + //! Channel D Enable mask + TC_CCDEN = TC0_CCDEN_bm, +}; + +//! Timer Counter Direction +enum tc_dir_t { + //! Counting up + TC_UP = 0, + //! Down Counting B + TC_DOWN = 1 +}; +//! Timer Counter Waveform Generator mode +enum tc_wg_mode_t { + //! TC in normal Mode + TC_WG_NORMAL = TC_WGMODE_NORMAL_gc, + //! TC in Frequency Generator mode + TC_WG_FRQ = TC_WGMODE_FRQ_gc, + //! TC in single slope PWM mode + TC_WG_SS = TC_WGMODE_SS_gc, + //! TC in dual slope Top PWM mode + TC_WG_DS_T = TC_WGMODE_DS_T_gc, + //! TC in dual slope Top Bottom PWM mode + TC_WG_DS_TB = TC_WGMODE_DS_TB_gc, + //! TC in dual slope Bottom PWM mode + TC_WG_DS_B = TC_WGMODE_DS_B_gc +}; + +//! TC interrupt levels +enum TC_INT_LEVEL_t { + TC_INT_LVL_OFF = 0x00, + TC_INT_LVL_LO = 0x01, + TC_INT_LVL_MED = 0x02, + TC_INT_LVL_HI = 0x03, +}; + +//! Macro to check if type of passed TC is TC1_t +#define tc_is_tc1(void) ((uint16_t)tc&0x40 ? true : false) +//! Macro to check if type of passed TC is TC0_t +#define tc_is_tc0(void) ((uint16_t)tc&0x40 ? false : true) + +/** + * \brief Enable TC + * + * Enables the TC. + * + * \param tc Pointer to TC module + * + * \note + * unmask TC clock (sysclk), but does not configure the TC clock source. + */ +void tc_enable(volatile void *tc); + +/** + * \brief Disable TC + * + * Disables the TC. + * + * \param tc Pointer to TC module + * + * \note + * mask TC clock (sysclk). + */ +void tc_disable(volatile void *tc); + +/** + * \ingroup tc_group + * \defgroup tc_interrupt_group Timer Counter (TC) interrupt management + * This group provides functions to configure TC module interrupts + * + * + * @{ + */ +/** + * \brief Set TC overflow interrupt callback function + * + * This function allows the caller to set and change the interrupt callback + * function. Without setting a callback function the interrupt handler in the + * driver will only clear the interrupt flags. + * + * \param tc Pointer to the Timer Counter (TC) base address + * \param callback Reference to a callback function + */ +void tc_set_overflow_interrupt_callback(volatile void *tc, + tc_callback_t callback); + +/** + * \brief Set TC error interrupt callback function + * + * This function allows the caller to set and change the interrupt callback + * function. Without setting a callback function the interrupt handler in the + * driver will only clear the interrupt flags. + * + * \param tc Pointer to the Timer Counter (TC) base address + * \param callback Reference to a callback function + */ +void tc_set_error_interrupt_callback(volatile void *tc, tc_callback_t callback); + +/** + * \brief Set TC Capture Compare Channel A interrupt callback function + * + * This function allows the caller to set and change the interrupt callback + * function. Without setting a callback function the interrupt handler in the + * driver will only clear the interrupt flags. + * + * \param tc Pointer to the Timer Counter (TC) base address + * \param callback Reference to a callback function + */ +void tc_set_cca_interrupt_callback(volatile void *tc, tc_callback_t callback); + +/** + * \brief Set TC Capture Compare Channel B interrupt callback function + * + * This function allows the caller to set and change the interrupt callback + * function. Without setting a callback function the interrupt handler in the + * driver will only clear the interrupt flags. + * + * \param tc Pointer to the Timer Counter (TC) base address + * \param callback Reference to a callback function + */ +void tc_set_ccb_interrupt_callback(volatile void *tc, tc_callback_t callback); + +/** + * \brief Set TC Capture Compare Channel C interrupt callback function + * + * This function allows the caller to set and change the interrupt callback + * function. Without setting a callback function the interrupt handler in the + * driver will only clear the interrupt flags. + * + * \param tc Pointer to the Timer Counter (TC) base address + * \param callback Reference to a callback function + */ +void tc_set_ccc_interrupt_callback(volatile void *tc, tc_callback_t callback); + +/** + * \brief Set TC Capture Compare Channel D interrupt callback function + * + * This function allows the caller to set and change the interrupt callback + * function. Without setting a callback function the interrupt handler in the + * driver will only clear the interrupt flags. + * + * \param tc Pointer to the Timer Counter (TC) base address + * \param callback Reference to a callback function + */ +void tc_set_ccd_interrupt_callback(volatile void *tc, tc_callback_t callback); +/** + * \brief Configures TC overflow Interrupt level + * + * \param tc Pointer to TC module. + * \param level Overflow interrupt level + * \note Configures OVFINTLVL in INTCTRLA + */ +static inline void tc_set_overflow_interrupt_level(volatile void *tc, + enum TC_INT_LEVEL_t level) +{ + ((TC0_t *)tc)->INTCTRLA = ((TC0_t *)tc)->INTCTRLA & ~TC0_OVFINTLVL_gm; + ((TC0_t *)tc)->INTCTRLA = + ((TC0_t *)tc)->INTCTRLA | (level << TC0_OVFINTLVL_gp); +} + +/** + * \brief Configures TC error Interrupt level + * + * \param tc Pointer to TC module. + * \param level Error interrupt level + * \note Configures ERRINTLVL in INTCTRLA + */ +static inline void tc_set_error_interrupt_level(volatile void *tc, + enum TC_INT_LEVEL_t level) +{ + ((TC0_t *)tc)->INTCTRLA = ((TC0_t *)tc)->INTCTRLA & ~TC0_ERRINTLVL_gm; + ((TC0_t *)tc)->INTCTRLA = + ((TC0_t *)tc)->INTCTRLA | (level << TC0_ERRINTLVL_gp); +} + +/** + * \brief Configures TC Capture Compare A Interrupt level + * + * \param tc Pointer to TC module. + * \param level CCA interrupt level + * \note Configures CCAINTLVL in INTCTRLB + */ +static inline void tc_set_cca_interrupt_level(volatile void *tc, + enum TC_INT_LEVEL_t level) +{ + ((TC0_t *)tc)->INTCTRLB = ((TC0_t *)tc)->INTCTRLB & ~TC0_CCAINTLVL_gm; + ((TC0_t *)tc)->INTCTRLB = + ((TC0_t *)tc)->INTCTRLB | (level << TC0_CCAINTLVL_gp); +} + +/** + * \brief Configures TC Capture Compare B Interrupt level + * + * \param tc Pointer to TC module. + * \param level CCB interrupt level + * \note Configures CCBINTLVL in INTCTRLB + */ +static inline void tc_set_ccb_interrupt_level(volatile void *tc, + enum TC_INT_LEVEL_t level) +{ + ((TC0_t *)tc)->INTCTRLB = ((TC0_t *)tc)->INTCTRLB & ~TC0_CCBINTLVL_gm; + ((TC0_t *)tc)->INTCTRLB = + ((TC0_t *)tc)->INTCTRLB | (level << TC0_CCBINTLVL_gp); +} + +/** + * \brief Configures TC Capture Compare C Interrupt level + * + * \param tc Pointer to TC module. + * \param level CCC interrupt level + * \note Configures CCCINTLVL in INTCTRLB + */ +static inline void tc_set_ccc_interrupt_level(volatile void *tc, + enum TC_INT_LEVEL_t level) +{ + ((TC0_t *)tc)->INTCTRLB = ((TC0_t *)tc)->INTCTRLB & ~TC0_CCCINTLVL_gm; + ((TC0_t *)tc)->INTCTRLB = + ((TC0_t *)tc)->INTCTRLB | (level << TC0_CCCINTLVL_gp); +} + + /** + * \brief Configures TC Capture Compare D Interrupt level + * + * \param tc Pointer to TC module. + * \param level CCD interrupt level + * \note Configures CCDINTLVL in INTCTRLB + */ +static inline void tc_set_ccd_interrupt_level(volatile void *tc, + enum TC_INT_LEVEL_t level) +{ + ((TC0_t *)tc)->INTCTRLB = ((TC0_t *)tc)->INTCTRLB & ~TC0_CCDINTLVL_gm; + ((TC0_t *)tc)->INTCTRLB = + ((TC0_t *)tc)->INTCTRLB | (level << TC0_CCDINTLVL_gp); +} + +//@} + +/** + * \brief Configure Timer Clock Source + * + * \param tc Pointer to TC module. + * \param TC_CLKSEL_enum Clock source selection + * \note Configuring the clock also starts the timer + */ +static inline void tc_write_clock_source(volatile void *tc, + TC_CLKSEL_t TC_CLKSEL_enum) +{ + ((TC0_t *)tc)->CTRLA = + (((TC0_t *)tc)->CTRLA & ~TC0_CLKSEL_gm) | + TC_CLKSEL_enum; +} + +/** + * \brief Read Timer Clock Source + * + * \param tc Pointer to TC module. + * \return TC_CLKSEL_enum Clock source selection + */ +static inline TC_CLKSEL_t tc_read_clock_source(volatile void *tc) +{ + return (TC_CLKSEL_t)(((TC0_t *)tc)->CTRLA & TC0_CLKSEL_gm); +} + +/** + * \brief Select clock for a specified TC and resolution. + * + * This function configures the clock selection, as prescaled CLKper, for a + * specified TC that gives a resolution at least as high as the one specified. + * The resolution of a TC is synonymous with its clock frequency. + * + * \note It is also possible to clock TCs with event channels. This is not + * handled by this implementation. + * + * \param tc ID of TC to get clock selection for. + * \param resolution Desired resolution for the TC in Hz. + */ +static inline void tc_set_resolution(void *tc, uint32_t resolution) +{ + uint32_t tc_clk_rate = sysclk_get_per_hz(); + + if (resolution <= (tc_clk_rate / 1024)) { + tc_write_clock_source(tc, TC_CLKSEL_DIV1024_gc); + } else if (resolution <= (tc_clk_rate / 256)) { + tc_write_clock_source(tc, TC_CLKSEL_DIV256_gc); + } else if (resolution <= (tc_clk_rate / 64)) { + tc_write_clock_source(tc, TC_CLKSEL_DIV64_gc); + } else if (resolution <= (tc_clk_rate / 8)) { + tc_write_clock_source(tc, TC_CLKSEL_DIV8_gc); + } else if (resolution <= (tc_clk_rate / 4)) { + tc_write_clock_source(tc, TC_CLKSEL_DIV4_gc); + } else if (resolution <= (tc_clk_rate / 2)) { + tc_write_clock_source(tc, TC_CLKSEL_DIV2_gc); + } else { + tc_write_clock_source(tc, TC_CLKSEL_DIV1_gc); + } +} + +/** + * \brief Get real resolution for a specified TC. + * + * This function returns the resolution which the specified clock selection + * of TC will result in. The resolution of a TC is synonymous with its clock + * frequency. + * + * \note This function does not handle event channel clock selections. + * + * \param tc Pointer of TC module to get resolution for. + * + * \return The resolution of \a tc. + */ +static inline uint32_t tc_get_resolution(void *tc) +{ + uint32_t tc_clk_rate = sysclk_get_per_hz(); + switch (tc_read_clock_source(tc)) { + case TC_CLKSEL_OFF_gc: + tc_clk_rate = 0; + break; + + case TC_CLKSEL_DIV1024_gc: + tc_clk_rate /= 1024; + break; + + case TC_CLKSEL_DIV256_gc: + tc_clk_rate /= 256; + break; + + case TC_CLKSEL_DIV64_gc: + tc_clk_rate /= 64; + break; + + case TC_CLKSEL_DIV8_gc: + tc_clk_rate /= 8; + break; + + case TC_CLKSEL_DIV4_gc: + tc_clk_rate /= 4; + break; + + case TC_CLKSEL_DIV2_gc: + tc_clk_rate /= 2; + break; + + case TC_CLKSEL_DIV1_gc: + break; + + default: + tc_clk_rate = 0; + break; + } + return (tc_clk_rate); +} + +/** + * \brief Configure Timer Direction + * + * \param tc Pointer to TC module. + * \param dir Timer direction : + */ +static inline void tc_set_direction(volatile void *tc, enum tc_dir_t dir) +{ + if (dir == TC_UP) { + ((TC0_t *)tc)->CTRLFCLR |= ~TC0_DIR_bm; + } else { + ((TC0_t *)tc)->CTRLFSET |= TC0_DIR_bm; + } +} + +/** + * \brief Write the Counter value of the Timer + * + * \param tc Pointer to TC module. + * \param cnt_value Counter value : + */ +static inline void tc_write_count(volatile void *tc, uint16_t cnt_value) +{ + ((TC0_t *)tc)->CNT = cnt_value; +} + +/** + * \brief Reads the Counter value of the Timer + * + * \param tc Pointer to TC module. + * \note Output the Counter value CNT + */ +static inline uint16_t tc_read_count(volatile void *tc) +{ + return (((TC0_t *)tc)->CNT); +} + +/** + * \brief Writes the Period value of the Timer + * + * \param tc Pointer to TC module. + * \param per_value Period value : PER + */ +static inline void tc_write_period(volatile void *tc, uint16_t per_value) +{ + ((TC0_t *)tc)->PER = per_value; +} + +/** + * \brief Reads the Period value of the Timer + * + * \param tc Pointer to TC module. + * \return Period value : PER + */ +static inline uint16_t tc_read_period(volatile void *tc) +{ + return (((TC0_t *)tc)->PER); +} + +/** + * \brief Writes the Period Buffer value of the Timer + * + * \param tc Pointer to TC module. + * \param per_buf Period Buffer value : PERH/PERL + */ +static inline void tc_write_period_buffer(volatile void *tc, uint16_t per_buf) +{ + ((TC0_t *)tc)->PERBUF = per_buf; +} + +/** + * \brief Reads the Period Buffer value of the Timer + * + * \param tc Pointer to TC module. + * \return Period Buffer value : PERH/PERL + */ +static inline uint16_t tc_read_period_buffer(volatile void *tc) +{ + return (((TC0_t *)tc)->PERBUF); +} + +/** + * \brief Tests if the Period Buffer is valid + * + * \param tc Pointer to TC module. + * \return period Buffer is valid or not:PERBV + */ +static inline bool tc_period_buffer_is_valid(volatile void *tc) +{ + return (((TC0_t *)tc)->CTRLGCLR & TC0_PERBV_bm); +} + +/** + * \brief Enables delay (used for 32bit timer mode) + * + * \param tc Pointer to TC module. + * \note enables Delay mode + */ +static inline void tc_enable_delay(volatile void *tc) +{ + ((TC0_t *)tc)->CTRLD = (((TC0_t *)tc)->CTRLD & + ~TC0_EVDLY_bm) | (1 << TC0_EVDLY_bp); +} + +/** + * \brief Disables delay + * + * \param tc Pointer to TC module. + * \note disables Delay mode + */ +static inline void tc_disable_delay(volatile void *tc) +{ + ((TC0_t *)tc)->CTRLD = ((TC0_t *)tc)->CTRLD & ~TC0_EVDLY_bm; +} + +/** + * \brief Tests if the Overflow flag is set + * + * \param tc Pointer to TC module. + * \return overflow has occurred or not : OVFIF + */ +static inline bool tc_is_overflow(volatile void *tc) +{ + return (((TC0_t *)tc)->INTFLAGS & TC0_OVFIF_bm); +} + +/** + * \brief Clears the Overflow flag + * + * \param tc Pointer to TC module. + * \note OVFIF is cleared + */ +static inline void tc_clear_overflow(volatile void *tc) +{ + ((TC0_t *)tc)->INTFLAGS |= TC0_OVFIF_bm; +} + +/** + * \brief Tests if the Error flag is set + * + * \param tc Pointer to TC module. + * \return Error has occurred or not : ERRIF + */ +static inline bool tc_read_error(volatile void *tc) +{ + return (((TC0_t *)tc)->INTFLAGS & TC0_ERRIF_bm); +} + +/** + * \brief Clears the Error flag + * + * \param tc Pointer to TC module. + * \note ERRIF is cleared + */ +static inline void tc_clear_error(volatile void *tc) +{ + ((TC0_t *)tc)->INTFLAGS |= TC0_ERRIF_bm; +} + +/** + * \brief Restart the Timer + * + * \param tc Pointer to TC module. + * \note CMD[3] in CTRLFSET is set to 1 and CMD[2] in CTRLFCLR is set + */ +static inline void tc_restart(volatile void *tc) +{ + ((TC0_t *)tc)->CTRLFSET = TC_CMD_RESTART_gc; +} + +/** + * \brief Reset the Timer + * + * \param tc Pointer to TC module. + * \note CMD[3:2] in CTRLFSET are set to 1 + */ +static inline void tc_reset(volatile void *tc) +{ + ((TC0_t *)tc)->CTRLFSET = TC_CMD_RESET_gc; +} + +/** + * \brief Update the Timer + * + * \param tc Pointer to TC module. + * \note CMD[2] in CTRLFSET is set to 1 and CMD[3] in CTRLFCLR is set + */ +static inline void tc_update(volatile void *tc) +{ + ((TC0_t *)tc)->CTRLFSET = TC_CMD_UPDATE_gc; +} + +/** + * \brief Configures the Timer in Byte mode + * + * \param tc Pointer to TC module. + * \note Configures BYTEM in CTRLE + */ +static inline void tc_set_8bits_mode(volatile void *tc) +{ +#ifdef TC0_BYTEM0_bm + ((TC0_t *)tc)->CTRLE |= TC0_BYTEM0_bm; +#else + ((TC0_t *)tc)->CTRLE |= TC0_BYTEM_bm; +#endif +} + +/** + * \brief Locks the Update of the Buffered registers + * + * \param tc Pointer to TC module. + * + * */ +static inline void tc_lock_update_buffers(volatile void *tc) +{ + ((TC0_t *)tc)->CTRLFSET |= TC0_LUPD_bm; +} + +/** + * \brief Unlocks the Update of the Buffered registers + * + * \param tc Pointer to TC module. + * \note Configures LUPD in CTRLFCLR + */ +static inline void tc_unlock_update_buffers(volatile void *tc) +{ + ((TC0_t *)tc)->CTRLFCLR |= TC0_LUPD_bm; +} + +/** + * \brief Enables Compare/Capture channel + * + * \param tc Pointer to TC module. + * \param enablemask CC channel + */ +static inline void tc_enable_cc_channels(volatile void *tc, + enum tc_cc_channel_mask_enable_t enablemask) +{ + if (tc_is_tc0(void *tc)) { + ((TC0_t *)tc)->CTRLB |= enablemask; + } else if (tc_is_tc1(void *tc)) { + ((TC1_t *)tc)->CTRLB |= + enablemask & (TC1_CCAEN_bm | TC1_CCBEN_bm); + } +} + +/** + * \brief Disables Compare/Capture channel + * + * \param tc Pointer to TC module. + * \param disablemask CC channel + */ +static inline void tc_disable_cc_channels(volatile void *tc, + enum tc_cc_channel_mask_enable_t disablemask) +{ + if (tc_is_tc0(void *tc)) { + ((TC0_t *)tc)->CTRLB &= ~disablemask; + } else if (tc_is_tc1(void *tc)) { + ((TC1_t *)tc)->CTRLB &= + ~(disablemask & TC0_CCAEN_bm & TC0_CCBEN_bm); + } +} + +/** + * \brief Enables Input capture mode + * + * \param tc Pointer to TC module. + * \param eventsource Source for the capture + * \param eventaction Event action capture type + */ +static inline void tc_set_input_capture(volatile void *tc, + TC_EVSEL_t eventsource, TC_EVACT_t eventaction) +{ + ((TC0_t *)tc)->CTRLD &= ~(TC0_EVSEL_gm | TC0_EVACT_gm); + ((TC0_t *)tc)->CTRLD |= ((uint8_t)eventsource | (uint8_t)eventaction); +} + +/** + * \brief Reads the Capture value + * + * \param tc Pointer to TC module. + * \param channel_index Channel x + * \return Read value of CCx + */ +static inline uint16_t tc_read_cc(volatile void *tc, + enum tc_cc_channel_t channel_index) +{ + if (tc_is_tc0(void *tc)) { + switch (channel_index) { + case TC_CCA: + return (((TC0_t *)tc)->CCA); + case TC_CCB: + return (((TC0_t *)tc)->CCB); + case TC_CCC: + return (((TC0_t *)tc)->CCC); + case TC_CCD: + return (((TC0_t *)tc)->CCD); + } + } else if (tc_is_tc1(void *tc)) { + switch (channel_index) { + case TC_CCA: + return (((TC1_t *)tc)->CCA); + case TC_CCB: + return (((TC1_t *)tc)->CCB); + default: + return (0); + } + } + return (0); +} + +/** + * \brief Writes the CC value + * + * \param tc Pointer to TC module. + * \param channel_index CC Channel + * \param value Counter value + */ +static inline void tc_write_cc(volatile void *tc, + enum tc_cc_channel_t channel_index, uint16_t value) +{ + if (tc_is_tc0(void *tc)) { + switch (channel_index) { + case TC_CCA: + ((TC0_t *)tc)->CCA = value; + break; + case TC_CCB: + ((TC0_t *)tc)->CCB = value; + break; + case TC_CCC: + ((TC0_t *)tc)->CCC = value; + break; + case TC_CCD: + ((TC0_t *)tc)->CCD = value; + break; + } + } else if (tc_is_tc1(void *tc)) { + switch (channel_index) { + case TC_CCA: + ((TC1_t *)tc)->CCA = value; + break; + case TC_CCB: + ((TC1_t *)tc)->CCB = value; + break; + default: + return ; + } + } +} + +/** + * \brief Writes the Capture/Compare Buffer value + * + * \param tc Pointer to TC module. + * \param channel_index CC Channel + * \param buffer_value Counter Buffer value + */ +static inline void tc_write_cc_buffer(volatile void *tc, + enum tc_cc_channel_t channel_index, uint16_t buffer_value) +{ + if (tc_is_tc0(void *tc)) { + switch (channel_index) { + case TC_CCA: + ((TC0_t *)tc)->CCABUF = buffer_value; + break; + case TC_CCB: + ((TC0_t *)tc)->CCBBUF = buffer_value; + break; + case TC_CCC: + ((TC0_t *)tc)->CCCBUF = buffer_value; + break; + case TC_CCD: + ((TC0_t *)tc)->CCDBUF = buffer_value; + break; + } + } else if (tc_is_tc1(void *tc)) { + switch (channel_index) { + case TC_CCA: + ((TC1_t *)tc)->CCABUF = buffer_value; + break; + case TC_CCB: + ((TC1_t *)tc)->CCBBUF = buffer_value; + break; + default: + return; + } + } +} + +/** + * \brief Reads the Capture/Compare Buffer value + * + * \param tc Pointer to TC module. + * \param channel_index CC Channel + * \return CCx Buffer value + */ +static inline uint16_t tc_read_cc_buffer(volatile void *tc, + enum tc_cc_channel_t channel_index) +{ + if (tc_is_tc0(void *tc)) { + switch (channel_index) { + case TC_CCA: + return (((TC0_t *)tc)->CCABUF); + case TC_CCB: + return (((TC0_t *)tc)->CCBBUF); + case TC_CCC: + return (((TC0_t *)tc)->CCCBUF); + case TC_CCD: + return (((TC0_t *)tc)->CCDBUF); + } + } else if (tc_is_tc1(void *tc)) { + switch (channel_index) { + case TC_CCA: + return (((TC1_t *)tc)->CCABUF); + case TC_CCB: + return (((TC1_t *)tc)->CCBBUF); + default: + return (0); + } + } + return (0); +} + +/** + * \brief Reports is Capture/Compare Buffer is valid + * + * \param tc Pointer to TC module. + * \param channel_index CC Channel + * \return CCx Buffer is valid or not + */ +static inline bool tc_cc_buffer_is_valid(volatile void *tc, + enum tc_cc_channel_t channel_index) +{ + if (tc_is_tc0(void *tc)) { + switch (channel_index) { + case TC_CCA: + return ((TC0_t *)tc)->CTRLGCLR & TC0_CCABV_bm; + case TC_CCB: + return ((TC0_t *)tc)->CTRLGCLR & TC0_CCBBV_bm; + case TC_CCC: + return ((TC0_t *)tc)->CTRLGCLR & TC0_CCCBV_bm; + case TC_CCD: + return ((TC0_t *)tc)->CTRLGCLR & TC0_CCDBV_bm; + } + } else if (tc_is_tc1(void *tc)) { + switch (channel_index) { + case TC_CCA: + return (((TC1_t *)tc)->CTRLGCLR & + TC1_CCABV_bm); + case TC_CCB: + return (((TC1_t *)tc)->CTRLGCLR & + TC1_CCBBV_bm); + default: + return (0); + } + } + return (0); +} + +/** + * \brief Reports if Capture/Compare interrupt has occurred + * + * \param tc Pointer to TC module. + * \param channel_index CC Channel + * \return CCx Interrupt or not + */ +static inline bool tc_is_cc_interrupt(volatile void *tc, + enum tc_cc_channel_t channel_index) +{ + if (tc_is_tc0(void *tc)) { + switch (channel_index) { + case TC_CCA: + return (((TC0_t *)tc)->INTFLAGS & TC0_CCAIF_bm); + case TC_CCB: + return (((TC0_t *)tc)->INTFLAGS & TC0_CCBIF_bm); + case TC_CCC: + return (((TC0_t *)tc)->INTFLAGS & TC0_CCCIF_bm); + case TC_CCD: + return (((TC0_t *)tc)->INTFLAGS & TC0_CCDIF_bm); + } + } else if (tc_is_tc1(void *tc)) { + switch (channel_index) { + case TC_CCA: + return (((TC1_t *)tc)->INTFLAGS & + TC1_CCAIF_bm); + case TC_CCB: + return (((TC1_t *)tc)->INTFLAGS & + TC1_CCBIF_bm); + default: + return (0); + } + } + return (0); +} + +/** + * \brief Clears Capture/Compare interrupt + * + * \param tc Pointer to TC module. + * \param channel_index CC Channel + */ +static inline void tc_clear_cc_interrupt(volatile void *tc, + enum tc_cc_channel_t channel_index) +{ + if (tc_is_tc0(void *tc)) { + switch (channel_index) { + case TC_CCA: + ((TC0_t *)tc)->INTFLAGS = TC0_CCAIF_bm; + break; + case TC_CCB: + ((TC0_t *)tc)->INTFLAGS = TC0_CCBIF_bm; + break; + case TC_CCC: + ((TC0_t *)tc)->INTFLAGS = TC0_CCCIF_bm; + break; + case TC_CCD: + ((TC0_t *)tc)->INTFLAGS = TC0_CCDIF_bm; + break; + } + } else if (tc_is_tc1(void *tc)) { + switch (channel_index) { + case TC_CCA: + ((TC1_t *)tc)->INTFLAGS = TC1_CCAIF_bm; + break; + case TC_CCB: + ((TC1_t *)tc)->INTFLAGS = TC1_CCBIF_bm; + break; + default: + return; + } + } +} + +/** + * \brief Configures TC in the specified Waveform generator mode + * + * \param tc Pointer to TC module. + * \param wgm : waveform generator + */ +static inline void tc_set_wgm(volatile void *tc, enum tc_wg_mode_t wgm) +{ + ((TC0_t *)tc)->CTRLB = (((TC0_t *)tc)->CTRLB & ~TC0_WGMODE_gm) | wgm; +} + +/** + * \ingroup tc_group + * \defgroup tc_awex_group AWeX extension driver + * This group provides low level drivers to configure AWeX extension + * @{ + */ + +/** + * \brief AWeX extension enable + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_enable_cwcm(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL |= AWEX_CWCM_bm; +} + +/** + * \brief AWeX extension disable Common waveform mode + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_disable_cwcm(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL &= ~AWEX_CWCM_bm; +} + +/** + * \brief AWeX extension enable pattern generator mode + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_enable_pgm(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL |= AWEX_PGM_bm; +} + +/** + * \brief AWeX extension disable pattern generator mode + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_disable_pgm(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL &= ~AWEX_PGM_bm; +} + +/** + * \brief AWeX extension : enable Deadtime insertion on ccA + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_enable_cca_deadtime(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL |= AWEX_DTICCAEN_bm; +} + +/** + * \brief AWeX extension : disable Deadtime insertion on ccA + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_disable_cca_deadtime(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL &= ~AWEX_DTICCAEN_bm; +} + +/** + * \brief AWeX extension : enable Deadtime insertion on ccB + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_enable_ccb_deadtime(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL |= AWEX_DTICCBEN_bm; +} + +/** + * \brief AWeX extension : disable Deadtime insertion on ccB + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_disable_ccb_deadtime(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL &= ~AWEX_DTICCBEN_bm; +} + +/** + * \brief AWeX extension : enable Deadtime insertion on ccC + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_enable_ccc_deadtime(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL |= AWEX_DTICCCEN_bm; +} + +/** + * \brief AWeX extension : disable Deadtime insertion on ccD + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_disable_ccc_deadtime(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL &= ~AWEX_DTICCCEN_bm; +} + +/** + * \brief AWeX extension : enable Deadtime insertion on ccD + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_enable_ccd_deadtime(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL |= AWEX_DTICCDEN_bm; +} + +/** + * \brief AWeX extension : disable Deadtime insertion on ccD + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_disable_ccd_deadtime(AWEX_t *awex) +{ + ((AWEX_t *)awex)->CTRL &= ~AWEX_DTICCDEN_bm; +} +/** + * \brief AWeX extension : configures high side deadtime + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \param value : deadtime value + */ +static inline void tc_awex_set_dti_high(AWEX_t *awex, int16_t value) +{ + ((AWEX_t *)awex)->DTHS = value; +} +/** + * \brief AWeX extension : configures low side deadtime + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \param value : deadtime value + */ +static inline void tc_awex_set_dti_low(AWEX_t *awex, int16_t value) +{ + ((AWEX_t *)awex)->DTLS = value; +} +/** + * \brief AWeX extension : configures symmetrical deadtime + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \param value : deadtime value + */ +static inline void tc_awex_set_dti_both(AWEX_t *awex, int16_t value) +{ + ((AWEX_t *)awex)->DTBOTH = value; +} + +/** + * \brief AWeX extension : configures symmetrical deadtime buffer + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \param value : deadtime buffer value + */ +static inline void tc_awex_set_dti_both_buffer(AWEX_t *awex, + int16_t value) +{ + ((AWEX_t *)awex)->DTBOTHBUF = value; +} + +/** + * \brief AWeX extension : returns the deadtime buffer high nibble + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \return Dead Time High value + */ +static inline int8_t tc_awex_get_dti_high_buffer(AWEX_t *awex) +{ + return (((AWEX_t *)awex)->DTHSBUF); +} + +/** + * \brief AWeX extension : returns the deadtime buffer low nibble + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \return Dead Time High value + */ +static inline int8_t tc_awex_get_dti_low_buffer(AWEX_t *awex) +{ + return (((AWEX_t *)awex)->DTLSBUF); +} + +/** + * \brief AWeX extension : returns if DTI high buffer is valid + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \return Dead Time High Buffer valid or not + */ +static inline bool tc_awex_is_dti_high_buffer_valid(AWEX_t *awex) +{ + return (((AWEX_t *)awex)->STATUS & AWEX_DTHSBUFV_bm); +} + +/** + * \brief AWeX extension : returns if DTI low buffer is valid + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \return Dead Time Low Buffer is valid or not + */ +static inline bool tc_awex_is_dti_low_buffer_valid(AWEX_t *awex) +{ + return (((AWEX_t *)awex)->STATUS & AWEX_DTLSBUFV_bm); +} + +/** + * \brief AWeX extension : configures the Fault restart in latched mode + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_fdmode_restart_latched(AWEX_t *awex) +{ + ((AWEX_t *)awex)->FDCTRL &= ~AWEX_FDMODE_bm; +} + +/** + * \brief AWeX extension : configures the Fault restart in cycle to cycle mode + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_fdmode_restart_cycle(AWEX_t *awex) +{ + ((AWEX_t *)awex)->FDCTRL |= AWEX_FDMODE_bm; +} + +/** + * \brief AWeX extension : returns if fault is detected + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline bool tc_awex_fault_is_detected(AWEX_t *awex) +{ + return (((AWEX_t *)awex)->STATUS & AWEX_FDF_bm); +} + +/** + * \brief AWeX extension : clears the Fault detection + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_clear_fault(AWEX_t *awex) +{ + ((AWEX_t *)awex)->STATUS = AWEX_FDF_bm; +} + +/** + * \brief AWeX extension : configures fault action + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \param fd_act Fault action + */ +static inline void tc_awex_set_fault_detection_action(AWEX_t * + awex, AWEX_FDACT_t fd_act) +{ + ((AWEX_t *)awex)->FDCTRL = (((AWEX_t *)awex)->FDCTRL & ~AWEX_FDACT_gm) | + (fd_act & AWEX_FDACT_gm); + +} + +/** + * \brief AWeX extension : configures fault detection event + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \param eventmask Fault detection event + */ +static inline void tc_awex_set_fault_detection_event(AWEX_t *awex, + int8_t eventmask) +{ + ((AWEX_t *)awex)->FDEMASK = eventmask; +} + +/** + * \brief AWeX extension : configures the port overdrive + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + * \param value Output override configuration + */ +static inline void tc_awex_set_output_override(AWEX_t * awex, + int8_t value) +{ + ((AWEX_t *)awex)->OUTOVEN = value; +} + +/** + * \brief AWeX extension : enable fault detection on debug break detection + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_enable_fault_debug_break(AWEX_t *awex) +{ + ((AWEX_t *)awex)->FDCTRL &= ~AWEX_FDDBD_bm; +} + +/** + * \brief AWeX extension : disable fault detection on debug break detection + * + * \param awex Pointer to AWeX module (AWEXC or AWEXE) + */ +static inline void tc_awex_disable_fault_debug_break(AWEX_t *awex) +{ + ((AWEX_t *)awex)->FDCTRL |= AWEX_FDDBD_bm; +} +//@} +/** + * \ingroup tc_group + * \defgroup tc_hires_group Hi-Res extension driver + * This group provides low level drivers to configure Hi-Res extension + * @{ + */ + +/** + * \brief Hi-Res Extension : configures the Hi-Res + * + * \param hires Pointer to AWeX module (AWEXC or AWEXE) + * \param hi_res_mode HIRES configuration + */ +static inline void tc_hires_set_mode(HIRES_t * hires, HIRES_HREN_t hi_res_mode) +{ + ((HIRES_t *)hires)->CTRLA = hi_res_mode; +} +//@} + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +/** + * \page xmega_tc_quickstart Quick Start Guide for the XMEGA TC Driver + * + * This is the quick start guide for the \ref tc_group , with step-by-step + * instructions on how to configure and use the driver for a specific use case. + * The code examples can be copied into e.g the main application loop or any + * other function that will need to control the timer/counters. + * + * + * \section xmega_tc_qs_use_cases Use cases + * - \ref xmega_tc_qs_ovf + * - \ref xmega_tc_qs_cc + * - \ref xmega_tc_qs_pwm + * + * + * \section xmega_tc_qs_ovf Timer/counter overflow (interrupt based) + * + * This use case will prepare a timer to trigger a interrupt when the timer + * overflows. The interrupt is handled by a cutomisable call back function. + * + * We will setup the timer in this mode: + * - Normal WGM mode (incrementing timer) + * - Use the system clock as clock source + * - No prescaling (DIV = 1) + * - Overflow interrupt after 1000 counts. This will be done by setting the top + * value to 1000. + * + * + * \section xmega_tc_qs_ovf_setup Setup steps + * + * \subsection xmega_tc_qs_ovf_usage_prereq Prequisites + * + * For the setup code of this use case to work, the following must + * be added to the project: + * - \ref interrupt_group + * - \ref clk_group + * + * \subsection xmega_tc_qs_ovf_setup_code Example code + * + * Add a callback function that will be executed when the overflow interrupt + * trigger. + * \code + * static void my_callback(void) + * { + * ...Add your code here. This code will be executed when the overflow occur... + * } + * \endcode + * Add to, e.g., the main loop in the application C-file: + * \code + * pmic_init(); + * sysclk_init(); + * tc_enable(&TCC0); + * tc_set_overflow_interrupt_callback(&TCC0, my_callback); + * tc_set_wgm(&TCC0, TC_WG_NORMAL); + * tc_write_period(&TCC0, 1000); + * tc_set_overflow_interrupt_level(&TCC0, TC_INT_LVL_LO); + * cpu_irq_enable(); + * tc_write_clock_source(&TCC0, TC_CLKSEL_DIV1_gc); + * \endcode + * + * \subsection xmega_tc_qs_ovf_setup_code_workflow Workflow + * + * -# Enable the interrupt controller: + * - \code pmic_init(); \endcode + * -# Enable the clock system: + * - \code sysclk_init(); \endcode + * -# Enable timer/counter TCC0 + * - \code tc_enable(&TCC0); \endcode + * - \note This will enable the clock system for the module + * -# Set the callback function for overflow interrupt + * - \code tc_set_overflow_interrupt_callback(&TCC0, my_callback); \endcode + * - \warning This function requires that the my_callback function is defined + * -# Set the desired waveform mode + * - \code tc_set_wgm(&TCC0, TC_WG_NORMAL); \endcode + * - \note In this case, we use normal mode where the timer increments it + count value until the TOP value is reached. The timer then reset + its count value to 0. + * -# Set the period + * - \code tc_write_period(&TCC0, 1000); \endcode + * - \note This will specify the TOP value of the counter. The timer will + * overflow and reset when this value is reached. + * -# Set the overflow interrupt level + * - \code tc_set_overflow_interrupt_level(&TCC0, TC_INT_LVL_LO); \endcode + * -# Enable interrupts: + * - \code cpu_irq_enable(); \endcode + * -# Set the clock source + * - \code tc_write_clock_source(&TCC0, TC_CLKSEL_DIV1_gc); \endcode + * - \warning When the clock source is set, the timer will start counting + * + * \section xmega_tc_qs_ovf_usage Usage steps + * + * - None. The timer will run in the background, and the code written in the + * call back function will execute each time the timer overflows. + * + * + * \section xmega_tc_qs_cc Timer/counter compare match (interrupt based) + * + * This use case will prepare a timer to trigger two independent interrupts + * when it reaches two different compare values. The period of the timer + * is customizable and the two compare matches will be handled by two separate + * interrupts implemented in call back functions. + * + * We will setup the timer in this mode: + * - Normal WGM mode - incrementing timer + * - Use the system clock as clock source + * - No prescaling (DIV = 1) + * - Period of timer 10000 counts + * - Compare match A interrupt trigger after 100 counts + * - Compare match B interrupt trigger after 1000 counts + * - If compare A and compare B match occur simultaneously, compare B + * should have higher priority + * + * + * \section xmega_tc_qs_cc_setup Setup steps + * + * \subsection xmega_tc_qs_cc_usage_prereq Prequisites + * For the setup code of this use case to work, the following must + * be added to the project: + * - \ref interrupt_group + * - \ref clk_group + * + * \subsection xmega_tc_qs_cc_setup_code Example code + * + * Add two callback functions that will be executed when compare match A and + * compare match B occurs + * \code + * static void my_cca_callback(void) + * { + * ...Add your code here. This code will be executed when a compare match + * occur on channel A... + * } + * static void my_ccb_callback(void) + * { + * ...Add your code here. This code will be executed when a compare match + * occur on channel B... + * } + * \endcode + * Add to, e.g., the main loop in the application C-file: + * \code + * pmic_init(); + * sysclk_init(); + * cpu_irq_enable(); + * tc_enable(&TCC0); + * tc_set_cca_interrupt_callback(&TCC0, my_cca_callback); + * tc_set_ccb_interrupt_callback(&TCC0, my_ccb_callback); + * tc_set_wgm(&TCC0, TC_WG_NORMAL); + * tc_write_period(&TCC0, 10000); + * tc_write_cc(&TCC0, TC_CCA, 100); + * tc_write_cc(&TCC0, TC_CCB, 1000); + * tc_enable_cc_channels(&TCC0,(TC_CCAEN | TC_CCBEN)); + * tc_set_cca_interrupt_level(&TCC0, TC_INT_LVL_LO); + * tc_set_ccb_interrupt_level(&TCC0, TC_INT_LVL_MED); + * tc_write_clock_source(&TCC0, TC_CLKSEL_DIV1_gc); + * \endcode + * + * \subsection xmega_tc_qs_cc_setup_code_workflow Workflow + * + * -# Enable the interrupt controller: + * - \code pmic_init(); \endcode + * -# Enable the clock system: + * - \code sysclk_init(); \endcode + * -# Enable interrupts: + * - \code cpu_irq_enable(); \endcode + * -# Enable timer/counter TCC0 + * - \code tc_enable(&TCC0); \endcode + * - \note This will enable the clock system for the module + * -# Set call back function for CCA interrupt + * - \code tc_set_cca_interrupt_callback(&TCC0, my_cca_callback); \endcode + * - \warning This function requires that the call back function is defined + * -# Set call back function for CCB interrupt + * - \code tc_set_ccb_interrupt_callback(&TCC0, my_ccb_callback); \endcode + * - \warning This function requires that the call back function is defined + * -# Set the desired waveform mode + * - \code tc_set_wgm(&TCC0, TC_WG_NORMAL); \endcode + * - \note In this case, we use normal mode where the timer increments it + count value until the TOP value is reached. The timer then reset + its count value to 0. + * -# Set the period + * - \code tc_write_period(&TCC0, 10000); \endcode + * - \note This will specify the TOP value of the counter. The timer will + * overflow and reset when this value is reached. + * -# Set compare match value on CCA + * - \code tc_write_cc(&TCC0, TC_CCA, 100); \endcode + * -# Set compare match value on CCB + * - \code tc_write_cc(&TCC0, TC_CCB, 1000); \endcode + * -# Enable compare channel A and compare channel B + * -\code tc_enable_cc_channels(&TCC0, (TC_CCAEN | TC_CCBEN)); \endcode + * -# Set interrupt level on channel A (low priority, see \ref TC_INT_LEVEL_t) + * - \code tc_set_cca_interrupt_level(&TCC0, TC_INT_LVL_LO); \endcode + * -# Set interrupt level on channel B (medium priority \ref TC_INT_LEVEL_t) + * - \code tc_set_ccb_interrupt_level(&TCC0, TC_INT_LVL_MED); \endcode + * -# Set the clock source + * - \code tc_write_clock_source(&TCC0, TC_CLKSEL_DIV1_gc); \endcode + * - \warning When the clock source is set, the timer will start counting + * + * \section xmega_tc_qs_cc_usage Usage steps + * + * - None. The timer will run in the background, and the code written in the + * call back functions will execute each time a compare match occur. + * + * + * \section xmega_tc_qs_pwm Timer/counter PWM + * + * This use case will setup a timer in PWM mode. For more details you can + * also look at the XMEGA PWM service. + * + * We will setup the timer in this mode: + * - Normal WGM mode - incrementing timer + * - Use the 2MHz oscillator as clock source (default) + * - 1Hz PWM frequency (2MHz clock, 1024x prescale, TOP value 1950) + * - 10% duty cycle (1:10 ratio between PER and CC register) + * - Output the PWM signal to a I/O port + * + * \section xmega_tc_qs_pwm_setup Setup steps + * + * \subsection xmega_tc_qs_pwm_usage_prereq Prequisites + * For the setup code of this use case to work, the following must + * be added to the project: + * - \ref clk_group + * + * \subsection xmega_tc_qs_pwm_setup_code Example code + * + * Add to, e.g., the main loop in the application C-file: + * \code + * board_init(); + * sysclk_init(); + * tc_enable(&TCE0); + * tc_set_wgm(&TCE0, TC_WG_SS); + * tc_write_period(&TCE0, 1950); + * tc_write_cc(&TCE0, TC_CCA, 195); + * tc_enable_cc_channels(&TCE0,TC_CCAEN); + * tc_write_clock_source(&TCE0, TC_CLKSEL_DIV1024_gc); + * \endcode + * + * \subsection xmega_tc_qs_pwm_setup_code_workflow Workflow + * + * -# Ensure that PWM I/O pin is configured as output + * - \code board_init(); \endcode + * \note The board_init(); function configures the I/O pins. If this function + * is not executed, the I/O pin must be configured as output manually + * -# Enable the clock system: + * - \code sysclk_init(); \endcode + * -# Enable timer/counter TCE0 + * - \code tc_enable(&TCE0); \endcode + * - \note This will enable the clock system for the module + * -# Set the desired waveform mode + * - \code tc_set_wgm(&TCE0, TC_WG_NORMAL); \endcode + * - \note In this case, we use normal mode where the timer increments it + * count value until the TOP value is reached. The timer then reset + * its count value to 0. + * -# Set the period + * - \code tc_write_period(&TCE0, 1950); \endcode + * - \note This will specify the TOP value of the counter. The timer will + * overflow and reset when this value is reached. + * -# Set compare match value on CCA + * - \code tc_write_cc(&TCC0, TC_CCA, 195); \endcode + * - \note The PWM duty cycle will be the ratio between PER and CCA, which + * is set by the tc_write_period() and tc_write_cc() functions. Use + * tc_write_cc() to change duty cycle run time (e.g to dim a LED). + * When CCA = 0, the duty cycle will be 0%. When CCA = PER (top value) + * the duty cycle will be 100%. + * -# Enable compare channel A + * -\code tc_enable_cc_channels(&TCE0,TC_CCAEN); \endcode + * -# Set the clock source + * - \code tc_write_clock_source(&TCE0, TC_CLKSEL_DIV1024_gc); \endcode + * - \warning When the clock source is set, the timer will start counting + * + * \section xmega_tc_qs_pwm_usage Usage steps + * - Use tc_write_cc() to change the duty cycle of the PWM signal + * - Use tc_write_period() to change the PWM frequency + */ + +#endif /* TC_H */ diff --git a/DSTAT-temp/src/asf/xmega/drivers/usart/usart.c b/DSTAT-temp/src/asf/xmega/drivers/usart/usart.c new file mode 100644 index 0000000..f1ff80c --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/usart/usart.c @@ -0,0 +1,491 @@ +/** + * \file + * + * \brief USART driver for AVR XMEGA. + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include + +#include "compiler.h" +#include "usart.h" +#include "sysclk.h" +#include "ioport.h" +#include "status_codes.h" + +/** + * \brief Enable the system clock to an USART module. + * + * This function will enable the system clock to the provided \arg usart + * module. + * + * \brief usart Pointer to an USART module. + */ +static inline void usart_enable_module_clock(USART_t *usart) +{ +#ifdef USARTC0 + if ((uintptr_t)usart == (uintptr_t)&USARTC0) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_USART0); + } +#endif +#ifdef USARTC1 + if ((uintptr_t)usart == (uintptr_t)&USARTC1) { + sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_USART1); + } +#endif +#ifdef USARTD0 + if ((uintptr_t)usart == (uintptr_t)&USARTD0) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_USART0); + } +#endif +#ifdef USARTD1 + if ((uintptr_t)usart == (uintptr_t)&USARTD1) { + sysclk_enable_module(SYSCLK_PORT_D, SYSCLK_USART1); + } +#endif +#ifdef USARTE0 + if ((uintptr_t)usart == (uintptr_t)&USARTE0) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_USART0); + } +#endif +#ifdef USARTE1 + if ((uintptr_t)usart == (uintptr_t)&USARTE1) { + sysclk_enable_module(SYSCLK_PORT_E, SYSCLK_USART1); + } +#endif +#ifdef USARTF0 + if ((uintptr_t)usart == (uintptr_t)&USARTF0) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_USART0); + } +#endif +#ifdef USARTF1 + if ((uintptr_t)usart == (uintptr_t)&USARTF1) { + sysclk_enable_module(SYSCLK_PORT_F, SYSCLK_USART1); + } +#endif +} + +/** + * \brief Initialize USART in RS232 mode. + * + * This function initializes the USART module in RS232 mode using the + * usart_rs232_options_t configuration structure and CPU frequency. + * + * \param usart The USART module. + * \param opt The RS232 configuration option. + * + * \retval true if the initialization was successfull + * \retval false if the initialization failed (error in baud rate calculation) + */ +bool usart_init_rs232(USART_t *usart, const usart_rs232_options_t *opt) +{ + bool result; + usart_enable_module_clock(usart); + usart_set_mode(usart, USART_CMODE_ASYNCHRONOUS_gc); + usart_format_set(usart, opt->charlength, opt->paritytype, + opt->stopbits); + result = usart_set_baudrate(usart, opt->baudrate, sysclk_get_per_hz()); + usart_tx_enable(usart); + usart_rx_enable(usart); + + return result; +} + +/** + * \brief Initialize USART in SPI master mode. + * + * This function initializes the USART module in SPI master mode using the + * usart_spi_options_t configuration structure and CPU frequency. + * + * \param usart The USART module. + * \param opt The RS232 configuration option. + */ +void usart_init_spi(USART_t *usart, const usart_spi_options_t *opt) +{ + usart_enable_module_clock(usart); + usart_set_mode(usart, USART_CMODE_MSPI_gc); + port_pin_t sck_pin; + + if (opt->spimode == 1 || opt->spimode == 3) { + /** \todo Fix when UCPHA_bm is added to header file. */ + usart->CTRLC |= 0x02; + } else { + /** \todo Fix when UCPHA_bm is added to header file. */ + usart->CTRLC &= ~0x02; + } + + /* configure Clock polarity using INVEN bit of the correct SCK I/O port **/ + if (opt->spimode == 2 || opt->spimode == 3) { +#ifdef USARTC0 + if ((uint16_t)usart == (uint16_t)&USARTC0) { + sck_pin = IOPORT_CREATE_PIN(PORTC, 1); + ioport_configure_port_pin(ioport_pin_to_port(sck_pin), + ioport_pin_to_mask(sck_pin), + IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH | + IOPORT_INV_ENABLED); + } +#endif +#ifdef USARTC1 + if ((uint16_t)usart == (uint16_t)&USARTC1) { + sck_pin = IOPORT_CREATE_PIN(PORTC, 5); + ioport_configure_port_pin(ioport_pin_to_port(sck_pin), + ioport_pin_to_mask(sck_pin), + IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH | + IOPORT_INV_ENABLED); + } +#endif +#ifdef USARTD0 + if ((uint16_t)usart == (uint16_t)&USARTD0) { + sck_pin = IOPORT_CREATE_PIN(PORTD, 1); + ioport_configure_port_pin(ioport_pin_to_port(sck_pin), + ioport_pin_to_mask(sck_pin), + IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH | + IOPORT_INV_ENABLED); + } +#endif +#ifdef USARTD1 + if ((uint16_t)usart == (uint16_t)&USARTD1) { + sck_pin = IOPORT_CREATE_PIN(PORTD, 5); + ioport_configure_port_pin(ioport_pin_to_port(sck_pin), + ioport_pin_to_mask(sck_pin), + IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH | + IOPORT_INV_ENABLED); + } +#endif +#ifdef USARTE0 + if ((uint16_t)usart == (uint16_t)&USARTE0) { + sck_pin = IOPORT_CREATE_PIN(PORTE, 1); + ioport_configure_port_pin(ioport_pin_to_port(sck_pin), + ioport_pin_to_mask(sck_pin), + IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH | + IOPORT_INV_ENABLED); + } +#endif +#ifdef USARTE1 + if ((uint16_t)usart == (uint16_t)&USARTE1) { + sck_pin = IOPORT_CREATE_PIN(PORTE, 5); + ioport_configure_port_pin(ioport_pin_to_port(sck_pin), + ioport_pin_to_mask(sck_pin), + IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH | + IOPORT_INV_ENABLED); + } +#endif +#ifdef USARTF0 + if ((uint16_t)usart == (uint16_t)&USARTF0) { + sck_pin = IOPORT_CREATE_PIN(PORTF, 1); + ioport_configure_port_pin(ioport_pin_to_port(sck_pin), + ioport_pin_to_mask(sck_pin), + IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH | + IOPORT_INV_ENABLED); + } +#endif +#ifdef USARTF1 + if ((uint16_t)usart == (uint16_t)&USARTF1) { + sck_pin = IOPORT_CREATE_PIN(PORTF, 5); + ioport_configure_port_pin(ioport_pin_to_port(sck_pin), + ioport_pin_to_mask(sck_pin), + IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH | + IOPORT_INV_ENABLED); + } +#endif + } + + usart_spi_set_baudrate(usart, opt->baudrate, sysclk_get_per_hz()); + usart_tx_enable(usart); + usart_rx_enable(usart); +} + +/** + * \brief Send a data with the USART module + * + * This function outputs a data using the USART module. + * + * \param usart The USART module. + * \param c The data to send. + * + * \return STATUS_OK + */ +enum status_code usart_putchar(USART_t *usart, uint8_t c) +{ + while (usart_data_register_is_empty(usart) == false) { + } + + (usart)->DATA = c; + return STATUS_OK; +} + +/** + * \brief Receive a data with the USART module + * + * This function returns the received data from the USART module. + * + * \param usart The USART module. + * + * \return The received data. + */ +uint8_t usart_getchar(USART_t *usart) +{ + while (usart_rx_is_complete(usart) == false) { + } + + return ((uint8_t)(usart)->DATA); +} + +/** + * \brief Get the offset for lookup in the baudrate table + * + * \param baud The requested baudrate + * + * \return The baudrate offset in PROGMEM table + * \retval USART_BAUD_UNDEFINED for baudrates not in lookup table + */ +static uint8_t usart_get_baud_offset(uint32_t baud) +{ + switch (baud) { + case 1200: + return (uint8_t)USART_BAUD_1200; + + case 2400: + return (uint8_t)USART_BAUD_2400; + + case 4800: + return (uint8_t)USART_BAUD_4800; + + case 9600: + return (uint8_t)USART_BAUD_9600; + + case 19200: + return (uint8_t)USART_BAUD_19200; + + case 38400: + return (uint8_t)USART_BAUD_38400; + + case 57600: + return (uint8_t)USART_BAUD_57600; + + default: + return (uint8_t)USART_BAUD_UNDEFINED; + } +} + +/** + * \brief Set the baudrate by setting the BSEL and BSCALE values in the USART + * + * This function sets the selected BSEL and BSCALE value in the BAUDCTRL + * registers with BSCALE 0. For calculation options, see table 21-1 in XMEGA A + * manual. + * + * \param usart The USART module. + * \param bsel Calculated BSEL value. + * \param bscale Calculated BSEL value. + * + */ +void usart_set_bsel_bscale_value(USART_t *usart, uint16_t bsel, uint8_t bscale) +{ + (usart)->BAUDCTRLA = (uint8_t)(bsel); + (usart)->BAUDCTRLB = (uint8_t)(((bsel >> 8) & 0X0F) | (bscale << 4)); +} + +/** + * \brief Set the baudrate using precalculated BAUDCTRL values from PROGMEM + * + * \note This function only works for cpu_hz 2Mhz or 32Mhz and baudrate values + * 1200, 2400, 4800, 9600, 19200, 38400 and 57600. + * + * \param usart The USART module. + * \param baud The baudrate. + * \param cpu_hz The CPU frequency. + * + */ +void usart_set_baudrate_precalculated(USART_t *usart, uint32_t baud, + uint32_t cpu_hz) +{ + uint8_t baud_offset; + uint16_t baudctrl = 0; + + baud_offset = usart_get_baud_offset(baud); + + if (cpu_hz == 2000000UL) { + baudctrl = PROGMEM_READ_WORD(baudctrl_2mhz + baud_offset); + } else if (cpu_hz == 32000000UL) { + baudctrl = PROGMEM_READ_WORD(baudctrl_32mhz + baud_offset); + } else { + /* Error, system clock speed or USART baud rate is not supported + * by the look-up table */ + Assert(false); + } + + if (baud_offset != USART_BAUD_UNDEFINED) { + (usart)->BAUDCTRLB = (uint8_t)((uint16_t)baudctrl); + (usart)->BAUDCTRLA = (uint8_t)((uint16_t)baudctrl >> 8); + } +} + +/** + * \brief Set the baudrate value in the USART module + * + * This function sets the baudrate register with scaling regarding the CPU + * frequency and makes sure the baud rate is supported by the hardware. + * The function can be used if you don't want to calculate the settings + * yourself or changes to baudrate at runtime is required. + * + * \param usart The USART module. + * \param baud The baudrate. + * \param cpu_hz The CPU frequency. + * + * \retval true if the hardware supports the baud rate + * \retval false if the hardware does not support the baud rate (i.e. it's + * either too high or too low.) + */ +bool usart_set_baudrate(USART_t *usart, uint32_t baud, uint32_t cpu_hz) +{ + int8_t exp; + uint32_t div; + uint32_t limit; + uint32_t ratio; + uint32_t min_rate; + uint32_t max_rate; + + /* + * Check if the hardware supports the given baud rate + */ + /* 8 = (2^0) * 8 * (2^0) = (2^BSCALE_MIN) * 8 * (BSEL_MIN) */ + max_rate = cpu_hz / 8; + /* 4194304 = (2^7) * 8 * (2^12) = (2^BSCALE_MAX) * 8 * (BSEL_MAX+1) */ + min_rate = cpu_hz / 4194304; + + if (!((usart)->CTRLB & USART_CLK2X_bm)) { + max_rate /= 2; + min_rate /= 2; + } + + if ((baud > max_rate) || (baud < min_rate)) { + return false; + } + + /* Check if double speed is enabled. */ + if (!((usart)->CTRLB & USART_CLK2X_bm)) { + baud *= 2; + } + + /* Find the lowest possible exponent. */ + limit = 0xfffU >> 4; + ratio = cpu_hz / baud; + + for (exp = -7; exp < 7; exp++) { + if (ratio < limit) { + break; + } + + limit <<= 1; + + if (exp < -3) { + limit |= 1; + } + } + + /* + * Depending on the value of exp, scale either the input frequency or + * the target baud rate. By always scaling upwards, we never introduce + * any additional inaccuracy. + * + * We are including the final divide-by-8 (aka. right-shift-by-3) in + * this operation as it ensures that we never exceeed 2**32 at any + * point. + * + * The formula for calculating BSEL is slightly different when exp is + * negative than it is when exp is positive. + */ + if (exp < 0) { + /* We are supposed to subtract 1, then apply BSCALE. We want to + * apply BSCALE first, so we need to turn everything inside the + * parenthesis into a single fractional expression. + */ + cpu_hz -= 8 * baud; + + /* If we end up with a left-shift after taking the final + * divide-by-8 into account, do the shift before the divide. + * Otherwise, left-shift the denominator instead (effectively + * resulting in an overall right shift.) + */ + if (exp <= -3) { + div = ((cpu_hz << (-exp - 3)) + baud / 2) / baud; + } else { + baud <<= exp + 3; + div = (cpu_hz + baud / 2) / baud; + } + } else { + /* We will always do a right shift in this case, but we need to + * shift three extra positions because of the divide-by-8. + */ + baud <<= exp + 3; + div = (cpu_hz + baud / 2) / baud - 1; + } + + (usart)->BAUDCTRLB = (uint8_t)(((div >> 8) & 0X0F) | (exp << 4)); + (usart)->BAUDCTRLA = (uint8_t)div; + + return true; +} + +/** + * \brief Set the baudrate value in the USART_SPI module + * + * This function sets the baudrate register regarding the CPU frequency. + * + * \param usart The USART(SPI) module. + * \param baud The baudrate. + * \param cpu_hz The CPU frequency. + */ +void usart_spi_set_baudrate(USART_t *usart, uint32_t baud, uint32_t cpu_hz) +{ + uint16_t bsel_value; + + /* Check if baudrate is less than the maximim limit specified in + * datasheet */ + if (baud < (cpu_hz / 2)) { + bsel_value = (cpu_hz / (baud * 2)) - 1; + } else { + /* If baudrate is not within the specfication in datasheet, + * assign maximum baudrate possible for the current CPU frequency */ + bsel_value = 0; + } + + (usart)->BAUDCTRLB = (uint8_t)((~USART_BSCALE_gm) & (bsel_value >> 8)); + (usart)->BAUDCTRLA = (uint8_t)(bsel_value); +} diff --git a/DSTAT-temp/src/asf/xmega/drivers/usart/usart.h b/DSTAT-temp/src/asf/xmega/drivers/usart/usart.h new file mode 100644 index 0000000..cf6ed28 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/usart/usart.h @@ -0,0 +1,555 @@ +/** + * \file + * + * \brief USART driver for AVR XMEGA. + * + * This file contains basic functions for the AVR XMEGA USART, with support for all + * modes, settings and clock speeds. + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef _USART_H_ +#define _USART_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "compiler.h" +#include "pmic.h" + +/** + * \defgroup usart_group USART module (USART) + * + * See \ref xmega_usart_quickstart. + * + * This is a driver for configuring, enabling, disabling and use of the on-chip + * USART. + * + * \section dependencies Dependencies + * + * The USART module depends on the following modules: + * - \ref sysclk_group for peripheral clock control. + * - \ref port_driver_group for peripheral io port control. + * + * @{ + */ + +//! Offset in lookup table for baudrate 1200 +#define USART_BAUD_1200 0x00 +//! Offset in lookup table for baudrate 2400 +#define USART_BAUD_2400 0x01 +//! Offset in lookup table for baudrate 4800 +#define USART_BAUD_4800 0x02 +//! Offset in lookup table for baudrate 9600 +#define USART_BAUD_9600 0x03 +//! Offset in lookup table for baudrate 19200 +#define USART_BAUD_19200 0x04 +//! Offset in lookup table for baudrate 38400 +#define USART_BAUD_38400 0x05 +//! Offset in lookup table for baudrate 57600 +#define USART_BAUD_57600 0x06 +//! Baudrate not in lookup table +#define USART_BAUD_UNDEFINED 0xFF + +//! Lookup table containing baudctrl values for CPU frequency 2 Mhz +static PROGMEM_DECLARE(uint16_t, baudctrl_2mhz[]) = { + 0xE5BC, // Baud: 1200 + 0xC5AC, // Baud: 2400 + 0x859C, // Baud: 4800 + 0x0396, // Baud: 9600 + 0xC192, // Baud: 19200 + 0x2191, // Baud: 38400 + 0x9690, // Baud: 57600 +}; + +//! Lookup table containing baudctrl values for CPU frequency 32 Mhz +static PROGMEM_DECLARE(uint16_t, baudctrl_32mhz[]) = { + 0x031D, // Baud: 1200 + 0x01ED, // Baud: 2400 + 0xFDDC, // Baud: 4800 + 0xF5CC, // Baud: 9600 + 0xE5BC, // Baud: 19200 + 0xC5AC, // Baud: 38400 + 0x6EA8, // Baud: 57600 +}; +//! @} + +//! Input parameters when initializing RS232 and similar modes. +typedef struct usart_rs232_options { + //! Set baud rate of the USART (unused in slave modes). + uint32_t baudrate; + + //! Number of bits to transmit as a character (5 to 9). + USART_CHSIZE_t charlength; + + //! Parity type: USART_PMODE_DISABLED_gc, USART_PMODE_EVEN_gc, + //! USART_PMODE_ODD_gc. + USART_PMODE_t paritytype; + + //! Number of stop bits between two characters: + //! true: 2 stop bits + //! false: 1 stop bit + bool stopbits; + +} usart_rs232_options_t; + +//! Input parameters when initializing SPI master mode. +typedef struct usart_spi_options { + //! Set baud rate of the USART in SPI mode. + uint32_t baudrate; + + //! SPI transmission mode. + uint8_t spimode; + + uint8_t data_order; +} usart_spi_options_t; + +//! USART interrupt levels +enum usart_int_level_t { + USART_INT_LVL_OFF = 0x00, + USART_INT_LVL_LO = 0x01, + USART_INT_LVL_MED = 0x02, + USART_INT_LVL_HI = 0x03, +}; + +/** + * \brief Enable USART receiver. + * + * \param usart Pointer to the USART module + */ +static inline void usart_rx_enable(USART_t *usart) +{ + (usart)->CTRLB |= USART_RXEN_bm; +} + +/** + * \brief Disable USART receiver. + * + * \param usart Pointer to the USART module. + */ +static inline void usart_rx_disable(USART_t *usart) +{ + (usart)->CTRLB &= ~USART_RXEN_bm; +} + +/** + * \brief Configure the USART frame format. + * + * Sets the frame format, Frame Size, parity mode and number of stop bits. + * + * \param usart Pointer to the USART module + * \param charSize The character size. Use USART_CHSIZE_t type. + * \param parityMode The parity Mode. Use USART_PMODE_t type. + * \param twoStopBits Enable two stop bit mode. Use bool type. + */ +static inline void usart_format_set(USART_t *usart, USART_CHSIZE_t charSize, + USART_PMODE_t parityMode, bool twoStopBits) +{ + (usart)->CTRLC = (uint8_t)charSize | parityMode + | (twoStopBits ? USART_SBMODE_bm : 0); +} + +/** + * \brief Enable USART transmitter. + * + * \param usart Pointer to the USART module. + */ +static inline void usart_tx_enable(USART_t *usart) +{ + (usart)->CTRLB |= USART_TXEN_bm; +} + +/** + * \brief Disable USART transmitter. + * + * \param usart Pointer to the USART module. + */ +static inline void usart_tx_disable(USART_t *usart) +{ + (usart)->CTRLB &= ~USART_TXEN_bm; +} + +/** + * \brief Set USART RXD interrupt level. + * + * Sets the interrupt level on RX Complete interrupt. + * + * \param usart Pointer to the USART module. + * \param level Interrupt level of the RXD interrupt. + */ +static inline void usart_set_rx_interrupt_level(USART_t *usart, + enum usart_int_level_t level) +{ + (usart)->CTRLA = ((usart)->CTRLA & ~USART_RXCINTLVL_gm) | + (level << USART_RXCINTLVL_gp); +} + +/** + * \brief Set USART TXD interrupt level. + * + * Sets the interrupt level on TX Complete interrupt. + * + * \param usart Pointer to the USART module. + * \param level Interrupt level of the TXD interrupt. + */ +static inline void usart_set_tx_interrupt_level(USART_t *usart, + enum usart_int_level_t level) +{ + (usart)->CTRLA = ((usart)->CTRLA & ~USART_TXCINTLVL_gm) | + (level << USART_TXCINTLVL_gp); +} + +/** + * \brief Set USART DRE interrupt level. + * + * Sets the interrupt level on Data Register interrupt. + * + * \param usart Pointer to the USART module. + * \param level Interrupt level of the DRE interrupt. + * Use USART_DREINTLVL_t type. + */ +static inline void usart_set_dre_interrupt_level(USART_t *usart, + enum usart_int_level_t level) +{ + (usart)->CTRLA = ((usart)->CTRLA & ~USART_DREINTLVL_gm) | + (level << USART_DREINTLVL_gp); +} + +/** + * \brief Set the mode the USART run in. + * + * Set the mode the USART run in. The default mode is asynchronous mode. + * + * \param usart Pointer to the USART module register section. + * \param usartmode Selects the USART mode. Use USART_CMODE_t type. + * + * USART modes: + * - 0x0 : Asynchronous mode. + * - 0x1 : Synchronous mode. + * - 0x2 : IrDA mode. + * - 0x3 : Master SPI mode. + */ +static inline void usart_set_mode(USART_t *usart, USART_CMODE_t usartmode) +{ + (usart)->CTRLC = ((usart)->CTRLC & (~USART_CMODE_gm)) | usartmode; +} + +/** + * \brief Check if data register empty flag is set. + * + * \param usart The USART module. + */ +static inline bool usart_data_register_is_empty(USART_t * usart) +{ + return (usart)->STATUS & USART_DREIF_bm; +} + +/** + * \brief Checks if the RX complete interrupt flag is set. + * + * Checks if the RX complete interrupt flag is set. + * + * \param usart The USART module. + */ +static inline bool usart_rx_is_complete(USART_t * usart) +{ + return (usart)->STATUS & USART_RXCIF_bm; +} + +/** + * \brief Checks if the TX complete interrupt flag is set. + * + * Checks if the TX complete interrupt flag is set. + * + * \param usart The USART module. + */ +static inline bool usart_tx_is_complete(USART_t * usart) +{ + return (usart)->STATUS & USART_TXCIF_bm; +} + +/** + * \brief Clear TX complete interrupt flag. + * + * \param usart The USART module. + */ +static inline void usart_clear_tx_complete(USART_t * usart) +{ + (usart)->STATUS = USART_TXCIF_bm; +} + +/** + * \brief Clear RX complete interrupt flag. + * + * \param usart The USART module. + */ +static inline void usart_clear_rx_complete(USART_t *usart) +{ + (usart)->STATUS = USART_RXCIF_bm; +} + +/** + * \brief Write a data to the USART data register. + * + * \param usart The USART module. + * \param txdata The data to be transmitted. + */ +static inline void usart_put(USART_t * usart, uint8_t txdata) +{ + (usart)->DATA = txdata; +} + +/** + * \brief Read a data to the USART data register. + * + * \param usart The USART module. + * + * \return The received data + */ +static inline uint8_t usart_get(USART_t * usart) +{ + return (usart)->DATA; +} + +/** + * \brief Performs a data transfer on the USART in SPI mode. + * + * \param usart The USART module. + * \param txdata The data to be transmitted. + * + * \return The received data + */ +static inline uint8_t usart_spi_transmit(USART_t * usart, + uint8_t txdata) +{ + while (usart_data_register_is_empty(usart) == false); + usart_put(usart, txdata); + while (!usart_tx_is_complete(usart)); + usart_clear_tx_complete(usart); + return usart_get(usart); +} + +bool usart_init_rs232(USART_t *usart, const usart_rs232_options_t *opt); +void usart_init_spi(USART_t * usart, const usart_spi_options_t * opt); + +enum status_code usart_putchar(USART_t * usart, uint8_t c); +uint8_t usart_getchar(USART_t * usart); + +void usart_set_bsel_bscale_value(USART_t *usart, uint16_t bsel, uint8_t bscale); +void usart_set_baudrate_precalculated(USART_t *usart, uint32_t baud, + uint32_t cpu_hz); +bool usart_set_baudrate(USART_t *usart, uint32_t baud, uint32_t cpu_hz); +void usart_spi_set_baudrate(USART_t * usart, uint32_t baud, uint32_t cpu_hz); +//! @} + +#ifdef __cplusplus +} +#endif + +/** + * \page xmega_usart_quickstart Quick start guide for USART module + * + * This is the quick start guide for the \ref usart_group "USART module", with + * step-by-step instructions on how to configure and use the driver in a + * selection of use cases. + * + * The use cases contain several code fragments. The code fragments in the + * steps for setup can be copied into a custom initialization function, while + * the steps for usage can be copied into, e.g., the main application function. + * + * \section usart_basic_use_case Basic use case + * \section usart_use_cases USART use cases + * - \ref usart_basic_use_case + * - \subpage usart_use_case_1 + * + * \section usart_basic_use_case Basic use case - transmit a character + * In this use case, the USART module is configured for: + * - Using USARTD0 + * - Baudrate: 9600 + * - Character length: 8 bit + * - Parity mode: Disabled + * - Stop bit: None + * - RS232 mode + * + * \section usart_basic_use_case_setup Setup steps + * + * \subsection usart_basic_use_case_setup_prereq Prerequisites + * -# \ref sysclk_group + * \subsection usart_basic_use_case_setup_code Example code + * The following configuration must be added to the project (typically to a + * conf_usart.h file, but it can also be added to your main application file.) + * \code + * #define USART_SERIAL &USARTD0 + * #define USART_SERIAL_BAUDRATE 9600 + * #define USART_SERIAL_CHAR_LENGTH USART_CHSIZE_8BIT_gc + * #define USART_SERIAL_PARITY USART_PMODE_DISABLED_gc + * #define USART_SERIAL_STOP_BIT false + * \endcode + * + * Add to application initialization: + * \code + * sysclk_init(); + * static usart_rs232_options_t USART_SERIAL_OPTIONS = { + * .baudrate = USART_SERIAL_BAUDRATE, + * .charlength = USART_SERIAL_CHAR_LENGTH, + * .paritytype = USART_SERIAL_PARITY, + * .stopbits = USART_SERIAL_STOP_BIT + * }; + * sysclk_enable_module(SYSCLK_PORT_D, PR_USART0_bm); + * usart_init_rs232(USART_SERIAL, &USART_SERIAL_OPTIONS); + * \endcode + * + * \subsection usart_basic_use_case_setup_flow Workflow + * -# Initialize system clock: + * - \code sysclk_init(); \endcode + * - \note Not always required, but since the \ref usart_group driver is + * dependent on \ref sysclk_group it is good practise to initialize + * this module. + * -# Create USART options struct: + * - \code + * static usart_rs232_options_t USART_SERIAL_OPTIONS = { + * .baudrate = USART_SERIAL_BAUDRATE, + * .charlength = USART_SERIAL_CHAR_LENGTH, + * .paritytype = USART_SERIAL_PARITY, + * .stopbits = USART_SERIAL_STOP_BIT + * }; + * \endcode + * -# Enable the clock for the USART module: + * - \code sysclk_enable_module(SYSCLK_PORT_D, PR_USART0_bm); \endcode + * -# Initialize in RS232 mode: + * - \code usart_init_rs232(USART_SERIAL, &USART_SERIAL_OPTIONS); + * \endcode + * + * \section usart_basic_use_case_usage Usage steps + * + * \subsection usart_basic_use_case_usage_code Example code + * Add to application C-file: + * \code + * usart_putchar(USART_SERIAL, 'a'); + * \endcode + * + * \subsection usart_basic_use_case_usage_flow Workflow + * -# Send an 'a' character via USART + * - \code usart_putchar(USART_SERIAL, 'a'); \endcode + */ + +/** + * \page usart_use_case_1 USART receive character and echo back + * + * In this use case, the USART module is configured for: + * - Using USARTD0 + * - Baudrate: 9600 + * - Character length: 8 bit + * - Parity mode: Disabled + * - Stop bit: None + * - RS232 mode + * + * The use case waits for a received character on the configured USART and + * echoes the character back to the same USART. + * + * \section usart_use_case_1_setup Setup steps + * + * \subsection usart_use_case_1_setup_prereq Prerequisites + * -# \ref sysclk_group + * + * \subsection usart_use_case_1_setup_code Example code + * -# The following configuration must be added to the project (typically to a + * conf_usart.h file, but it can also be added to your main application file.): + * \code + * #define USART_SERIAL &USARTD0 + * #define USART_SERIAL_BAUDRATE 9600 + * #define USART_SERIAL_CHAR_LENGTH USART_CHSIZE_8BIT_gc + * #define USART_SERIAL_PARITY USART_PMODE_DISABLED_gc + * #define USART_SERIAL_STOP_BIT false + * \endcode + * + * A variable for the received byte must be added: + * \code uint8_t received_byte; \endcode + * + * Add to application initialization: + * \code + * sysclk_init(); + * static usart_rs232_options_t USART_SERIAL_OPTIONS = { + * .baudrate = USART_SERIAL_BAUDRATE, + * .charlength = USART_SERIAL_CHAR_LENGTH, + * .paritytype = USART_SERIAL_PARITY, + * .stopbits = USART_SERIAL_STOP_BIT + * }; + * sysclk_enable_module(SYSCLK_PORT_D, PR_USART0_bm); + * usart_init_rs232(USART_SERIAL, &USART_SERIAL_OPTIONS); + * \endcode + * + * \subsection usart_use_case_1_setup_flow Workflow + * -# Initialize system clock: + * - \code sysclk_init(); \endcode + * - \note Not always required, but since the \ref usart_group driver is + * dependent on \ref sysclk_group it is good practise to initialize + * this module. + * -# Create USART options struct: + * - \code + * static usart_rs232_options_t USART_SERIAL_OPTIONS = { + * .baudrate = USART_SERIAL_BAUDRATE, + * .charlength = USART_SERIAL_CHAR_LENGTH, + * .paritytype = USART_SERIAL_PARITY, + * .stopbits = USART_SERIAL_STOP_BIT + * }; + * \endcode + * -# Enable the clock for the USART module: + * - \code sysclk_enable_module(SYSCLK_PORT_D, PR_USART0_bm); \endcode + * -# Initialize in RS232 mode: + * - \code usart_init_rs232(USART_SERIAL, &USART_SERIAL_OPTIONS); + * \endcode + * + * \section usart_use_case_1_usage Usage steps + * + * \subsection usart_use_case_1_usage_code Example code + * Add to, e.g., main loop in application C-file: + * \code + * received_byte = usart_getchar(USART_SERIAL); + * usart_putchar(USART_SERIAL, received_byte); + * \endcode + * + * \subsection usart_use_case_1_usage_flow Workflow + * -# Wait for reception of a character: + * - \code received_byte = usart_getchar(USART_SERIAL); \endcode + * -# Echo the character back: + * - \code usart_putchar(USART_SERIAL, received_byte); \endcode + */ + +#endif // _USART_H_ diff --git a/DSTAT-temp/src/asf/xmega/drivers/usb/usb_device.c b/DSTAT-temp/src/asf/xmega/drivers/usb/usb_device.c new file mode 100644 index 0000000..80ae4ca --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/usb/usb_device.c @@ -0,0 +1,1448 @@ +/** + * \file + * + * \brief USB Device driver + * Compliance with common driver UDD + * + * Copyright (c) 2011 - 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#include "conf_usb.h" + +// Read Modify Write opcode is implemented after IAR AVR 5.51 +#ifdef __ICCAVR__ +# if (__VER__ <= 551 || (__VER__ <= 611 && XMEGA_A1U) ) +# undef USB_WORKAROUND_DO_NOT_USE_RMW +# define USB_WORKAROUND_DO_NOT_USE_RMW +# endif +#endif + +#include "sysclk.h" +#include "udd.h" +#include "usb_device.h" +#include + +#ifndef UDD_NO_SLEEP_MGR +#include "sleepmgr.h" +#endif + +#ifndef UDD_USB_INT_LEVEL +// By default USB interrupt have low priority +# define UDD_USB_INT_LEVEL USB_INTLVL_LO_gc +#endif + + + +#ifdef USB_DEVICE_HS_SUPPORT +#error This product does not support high speed mode, please remove define USB_DEVICE_HS_SUPPORT in conf_usb.h +#endif + +//////////////////////////////////////////////////// +// USBB Device low-level driver (UDD) +//////////////////////////////////////////////////// +/** + * \ingroup udd_group + * \defgroup udd_xmega_usb_group Xmega USB Device Driver + * + * \section USBB_CONF USBB Custom configuration + * The following USBB driver configuration must be included in the conf_usb.h + * file of the application. + * + * UDD_USB_INT_LEVEL
+ * Option to change the interrupt priority (USB_INTLVL_x_gc) + * by default USB_INTLVL_LO_gc (recommended). + * + * \section Callbacks management + * The USB driver is fully managed by interrupt and does not request periodic + * task. Thereby, the USB events use callbacks to transfer the information. + * The callbacks are declared in static during compilation or in variable during + * code execution. + * + * Static declarations defined in conf_usb.h: + * - UDC_VBUS_EVENT(bool b_present)
+ * To signal Vbus level change + * - UDC_SUSPEND_EVENT()
+ * Called when USB bus enter in suspend mode + * - UDC_RESUME_EVENT()
+ * Called when USB bus is wakeup + * - UDC_SOF_EVENT()
+ * Called for each received SOF, Note: Each 1ms in HS/FS mode only. + * + * Dynamic callbacks, called "endpoint job" , are registered + * in udd_ep_job_t structure via the following functions: + * - udd_ep_run()
+ * To call it when a transfer is finish + * - udd_ep_wait_stall_clear()
+ * To call it when a endpoint halt is disabled + * + * \section Power mode management + * The Sleep modes authorized : + * - in USB IDLE state, the USB needs of USB clock and authorizes up to IDLE mode + * - in USB SUSPEND state, the USB no needs USB clock but requests a minimum + * clock restart timing. Thus, it authorizes up to POWER_DOWN or STANDBY mode. + * + * The USB_SLEEP_MODE_USB_IDLE equals SLEEPMGR_IDLE. + * + * The USB_SLEEP_MODE_USB_SUSPEND depends on USB clock startup timing: + * | Clock Startup | Sleep mode authorized | + * | >10ms | SLEEPMGR_STDBY | + * | <=10ms | SLEEPMGR_PDOWN | + * + * @{ + */ + + +// Check USB Device configuration +#ifndef USB_DEVICE_EP_CTRL_SIZE +# error USB_DEVICE_EP_CTRL_SIZE not defined +#endif +#ifndef USB_DEVICE_MAX_EP +# error USB_DEVICE_MAX_EP not defined +#endif + + +/** + * \name Power management routine. + */ +//@{ + + +#ifndef UDD_NO_SLEEP_MGR + +//! Definition of sleep levels +#if ((defined USB_DEVICE_HS_SUPPORT) && (USBCLK_STARTUP_TIMEOUT>3000)) \ + || ((!defined USB_DEVICE_HS_SUPPORT) && (USBCLK_STARTUP_TIMEOUT>10000)) +# define USBC_SLEEP_MODE_USB_SUSPEND SLEEPMGR_IDLE +#else +# define USBC_SLEEP_MODE_USB_SUSPEND SLEEPMGR_PDOWN +#endif +#define USBC_SLEEP_MODE_USB_IDLE SLEEPMGR_IDLE + +//! State of USB line +static bool udd_b_idle; + + +/*! \brief Authorize or not the CPU powerdown mode + * + * \param b_enable true to authorize powerdown mode + */ +static void udd_sleep_mode(bool b_idle) +{ + if (!b_idle && udd_b_idle) { + sleepmgr_unlock_mode(USBC_SLEEP_MODE_USB_IDLE); + } + if (b_idle && !udd_b_idle) { + sleepmgr_lock_mode(USBC_SLEEP_MODE_USB_IDLE); + } + udd_b_idle = b_idle; +} +#else + +static void udd_sleep_mode(bool b_idle) { +} +#endif // UDD_NO_SLEEP_MGR + +//@} + +/** + * \brief USB SRAM data about fifo, endpoint descriptor table and frame number + * + * The content of the USB SRAM can be: + * - modified by USB hardware by interface to signal endpoint status. + * Thereby, it is read by software. + * - modified by USB software to control endpoint. + * Thereby, it is read by hardware. + * This data section is volatile and the specific opcode read/modify/write must be used. + * + * @{ + */ +struct udd_sram_data { +#if XMEGA_A1U +# if (0!=((USB_DEVICE_MAX_EP+1)%4)) + uint8_t padding_align[16 - ((USB_DEVICE_MAX_EP + 1) * + sizeof(uint32_t)) % 16]; +# endif +#endif + uint32_t fifo[USB_DEVICE_MAX_EP + 1]; + USB_EP_t ep_ctrl[2 * (USB_DEVICE_MAX_EP + 1)]; + uint16_t frame_number; +}; +#if XMEGA_A1U +COMPILER_ALIGNED(16) +#else +COMPILER_ALIGNED(4) //! Caution seems GCC does not handle 2 alignment properly +#endif +static volatile struct udd_sram_data udd_sram; +#define UDD_EP_t USB_EP_t volatile + +// @} + +/** + * \name initialization of endpoint + */ +//@{ +/** + * \brief Configures and enables an endpoint + * + * \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT). + * \param bmAttributes Attribute of endpoint declared in descriptor. + * \param MaxEndpointSize Endpoint size maximum + */ +static void udd_ep_init(udd_ep_id_t ep, uint8_t bmAttributes, + uint16_t MaxEndpointSize); + +/** + * \brief Returns a pointer on endpoint control SRAM corresponding at endpoint number + * + * \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT). + * + * \return endpoint descriptor index + */ +static UDD_EP_t *udd_ep_get_ctrl(udd_ep_id_t ep); +//@} + + +/** + * \name Control endpoint low level management routine. + * + * This function performs control endpoint management. + * It handle the SETUP/DATA/HANDSHAKE phases of a control transaction. + */ +//@{ + +//! Global variable to give and record information about setup request management +udd_ctrl_request_t udd_g_ctrlreq; + +//! Bit definitions about endpoint control state machine for udd_ep_control_state +typedef enum { + UDD_EPCTRL_SETUP = 0, //!< Wait a SETUP packet + UDD_EPCTRL_DATA_OUT = 1, //!< Wait a OUT data packet + UDD_EPCTRL_DATA_IN = 2, //!< Wait a IN data packet + UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP = 3, //!< Wait a IN ZLP packet + UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP = 4, //!< Wait a OUT ZLP packet + UDD_EPCTRL_STALL_REQ = 5, //!< STALL enabled on IN & OUT packet +} udd_ctrl_ep_state_t; + +//! State of the endpoint control management +static udd_ctrl_ep_state_t udd_ep_control_state; +//! Total number of data received/sent during data packet phase with previous payload buffers +static uint16_t udd_ctrl_prev_payload_nb_trans; +//! Number of data received/sent to/from udd_g_ctrlreq.payload buffer +static uint16_t udd_ctrl_payload_nb_trans; + +/** + * \brief Buffer to store the data received on control endpoint (SETUP/OUT endpoint 0) + * + * Used to avoid a RAM buffer overflow in case of the payload buffer + * is smaller than control endpoint size + */ +static uint8_t udd_ctrl_buffer[USB_DEVICE_EP_CTRL_SIZE]; + +/** + * \brief Reset control endpoint management + * + * Called after a USB line reset or at the end of SETUP request (after ZLP) + */ +static void udd_ctrl_init(void); + +//! \brief Managed reception of SETUP packet on control endpoint +static void udd_ctrl_setup_received(void); + +//! \brief Managed reception of IN packet on control endpoint +static void udd_ctrl_in_sent(void); + +//! \brief Managed reception of OUT packet on control endpoint +static void udd_ctrl_out_received(void); + +//! \brief Managed underflow event of IN packet on control endpoint +//! It is used to detect a DATA phase stopped by the host via a ZLP request. +//! This is mandatory for chapter 8 compliance +static void udd_ctrl_underflow(void); + +//! \brief Managed overflow event of OUT packet on control endpoint +//! It is used to detect a DATA phase stopped by the host via a ZLP request. +//! This is mandatory for chapter 8 compliance +static void udd_ctrl_overflow(void); + +//! \brief Managed stall event of IN/OUT packet on control endpoint +static void udd_ctrl_stall_data(void); + +//! \brief Send a ZLP IN on control endpoint +static void udd_ctrl_send_zlp_in(void); + +//! \brief Send a ZLP OUT on control endpoint +static void udd_ctrl_send_zlp_out(void); + +//! \brief Call callback associated to setup request +static void udd_ctrl_endofrequest(void); + +/** + * \brief Sub interrupt routine to manage error on control endpoint + * + * \return \c 1 if an error about control endpoint is occurred, otherwise \c 0. + */ +static bool udd_ctrl_interrupt_error(void); + +/** + * \brief Sub interrupt routine to manage a SETUP transfer complete on control endpoint + * + * \return \c 1 if an SETUP transfer complete about control endpoint is occurred, + * otherwise \c 0. + */ +static bool udd_ctrl_interrupt_tc_setup(void); + +//@} + + +/** + * \name Management of bulk/interrupt/isochronous endpoints + * + * The UDD manages the data transfer on endpoints: + * - Start data transfer on endpoint with USB Device DMA + * - Send a ZLP packet if requested + * - Call callback registered to signal end of transfer + * The transfer abort and stall feature are supported. + */ +//@{ +#if (0!=USB_DEVICE_MAX_EP) + +//! Structure definition about job registered on an endpoint +typedef struct { + //! A job is registered on this endpoint + uint8_t busy:1; + //! A short packet is requested for this job on endpoint IN + uint8_t b_shortpacket:1; + //! The cache buffer is currently used on endpoint OUT + uint8_t b_use_out_cache_buffer:1; + //! Buffer located in internal RAM to send or fill during job + uint8_t *buf; + //! Size of buffer to send or fill + iram_size_t buf_size; + //! Total number of data transfered on endpoint + iram_size_t nb_trans; + union { + //! Callback to call at the end of transfer + udd_callback_trans_t call_trans; + //! Callback to call when the endpoint halt is cleared + udd_callback_halt_cleared_t call_nohalt; + }; +} udd_ep_job_t; + +//! Array to register a job on bulk/interrupt/isochronous endpoint +static udd_ep_job_t udd_ep_job[USB_DEVICE_MAX_EP * 2]; + +/** + * \brief Buffer to store the data received on bulk/interrupt endpoints + * + * Used to avoid a RAM buffer overflow in case of the user buffer + * is smaller than endpoint size + * + * \warning The isochronous endpoint is not protected by this system + * and the user must always use a buffer corresponding at endpoint size + */ +#ifdef USB_DEVICE_LOW_SPEED +static uint8_t udd_ep_out_cache_buffer[USB_DEVICE_MAX_EP][8]; +#else +static uint8_t udd_ep_out_cache_buffer[USB_DEVICE_MAX_EP][64]; +#endif + + +/** + * \brief Checks endpoint number + * + * \param ep endpoint number + */ +bool udd_ep_is_valid(udd_ep_id_t ep); + +/** + * \brief Manages transfer complete on bulk/interrupt/isochronous endpoints + * + * \param ep endpoint number to manage + */ +static void udd_ep_trans_complet(udd_ep_id_t ep); + +/** + * \brief Returns the size of endpoint + * + * \return the size of current selected endpoint + */ +static uint16_t udd_ep_get_size(UDD_EP_t * ep_ctrl); + +/** + * \brief Returns a pointer on endpoint job corresponding at endpoint number + * + * \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT). + */ +static udd_ep_job_t *udd_ep_get_job(udd_ep_id_t ep); + +#endif // (0!=USB_DEVICE_MAX_EP) +//@} + + +void udd_enable(void) +{ + uint8_t i; + irqflags_t flags; + + // Sanity check Silicon revision +#if AVR8_PART_IS_DEFINED(ATxmega128A1U) + // The part ATxmega128A1U Rev. J is not supported, please use new silicon revision. + Assert(!(MCU_REVID < 0x0A)); +#endif + +#ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC +# if CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC == OSC_ID_USBSOF + // RC oscillator calibration via USB Start Of Frame is not available + // in low speed mode. + // Thus, the calibration is disabled + // when USB interface start in low speed mode + DFLLRC32M.CTRL = 0; +# endif +#endif + +#ifdef USB_DEVICE_LOW_SPEED + // The USB hardware need of 6MHz in low speed mode + sysclk_enable_usb(6); + udd_set_low_speed(); +#else + // The USB hardware need of 48MHz in full speed mode + sysclk_enable_usb(48); + udd_set_full_speed(); +#endif + +// The XMEGA_A1U does not support the RC calibration through Keepalive (Low speed). +#if (!defined USB_DEVICE_LOW_SPEED) || (!XMEGA_A1U) +# ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC +# if CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC == OSC_ID_USBSOF + // The SOF calibration can be enabled + DFLLRC32M.CTRL = DFLL_ENABLE_bm; +# endif +# endif +#endif + + flags = cpu_irq_save(); + + // Reset endpoints table + for (i = 0; i < ((USB_DEVICE_MAX_EP + 1) * 2); i++) { + udd_sram.ep_ctrl[i].CTRL = 0; + } +#if (0!=USB_DEVICE_MAX_EP) + // Reset internal variables + for (i = 0; i < (USB_DEVICE_MAX_EP * 2); i++) { + udd_ep_job[i].busy = false; + } +#endif + + //** Enable USB hardware + usb_pad_init(); + udd_set_nb_max_ep(USB_DEVICE_MAX_EP); + udd_enable_interface(); + udd_enable_store_frame_number(); + udd_set_ep_table_addr(udd_sram.ep_ctrl); + // Enable TC fifo management + udd_enable_fifo(); + udd_reset_fifo(); + // Enable Interrupt USB Device + udd_enable_interrupt(UDD_USB_INT_LEVEL); + +#ifndef UDD_NO_SLEEP_MGR + // Initialize the sleep mode authorized for the USB suspend mode + udd_b_idle = false; + sleepmgr_lock_mode(USBC_SLEEP_MODE_USB_SUSPEND); +#endif + + cpu_irq_restore(flags); +} + + +void udd_disable(void) +{ + irqflags_t flags; + flags = cpu_irq_save(); + udd_detach_device(); + // Disable interface + USB_CTRLA = 0; + USB_CTRLB = 0; + sysclk_disable_usb(); + udd_sleep_mode(false); +#ifndef UDD_NO_SLEEP_MGR + sleepmgr_unlock_mode(USBC_SLEEP_MODE_USB_SUSPEND); +#endif + cpu_irq_restore(flags); +} + +bool udd_include_vbus_monitoring(void) +{ + return false; // No Vbus monitoring +} + +void udd_attach(void) +{ + irqflags_t flags; + flags = cpu_irq_save(); + + // At startup the USB bus state is unknown, + // therefore the state is considered IDLE to not miss any USB event + udd_sleep_mode(true); + + udd_ack_suspend_event(); + udd_ack_resume_event(); + udd_attach_device(); + // Enable main USB interrupts + udd_enable_tc_interrupt(); + udd_enable_busevt_interrupt(); + udd_enable_setup_interrupt(); + udd_enable_start_of_frame_interrupt(); + + cpu_irq_restore(flags); +} + +void udd_detach(void) +{ + // Detach device from the bus + udd_detach_device(); +} + +bool udd_is_high_speed(void) +{ + return false; +} + +void udd_set_address(uint8_t address) +{ + udd_set_device_address(address); +} + +uint8_t udd_getaddress(void) +{ + return udd_get_device_address(); +} + +uint16_t udd_get_frame_number(void) +{ + return udd_sram.frame_number; +} + +uint16_t udd_get_micro_frame_number(void) +{ + return 0; +} + +void udd_send_remotewakeup(void) +{ +#ifndef UDD_NO_SLEEP_MGR + if (!udd_b_idle) +#endif + { + udd_sleep_mode(true); // Enter in IDLE mode + udd_send_remote_wake_up(); + } +} + +void udd_set_setup_payload( uint8_t *payload, uint16_t payload_size ) +{ + udd_g_ctrlreq.payload = payload; + udd_g_ctrlreq.payload_size = payload_size; +} + +#if (0!=USB_DEVICE_MAX_EP) +bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes, + uint16_t MaxEndpointSize) +{ + UDD_EP_t *ep_ctrl; + Assert(udd_ep_is_valid(ep)); + + ep_ctrl = udd_ep_get_ctrl(ep); + if (udd_endpoint_is_enable(ep_ctrl)) { + return false; // Already allocated + } + udd_ep_init(ep, bmAttributes, MaxEndpointSize); + + // Do not use multipacket mode with isochronous 1023 bytes endpoint + if (udd_endpoint_get_type(ep_ctrl)==USB_EP_TYPE_ISOCHRONOUS_gc + && (udd_endpoint_get_size_field(ep_ctrl) + ==USB_EP_BUFSIZE_1023_gc)) { + return true; + } + + udd_endpoint_set_multipacket(ep_ctrl); + return true; +} + +void udd_ep_free(udd_ep_id_t ep) +{ + UDD_EP_t *ep_ctrl; + Assert(udd_ep_is_valid(ep)); + + udd_ep_abort(ep); + ep_ctrl = udd_ep_get_ctrl(ep); + udd_endpoint_disable(ep_ctrl); +} + +bool udd_ep_is_halted(udd_ep_id_t ep) +{ + UDD_EP_t *ep_ctrl; + Assert(udd_ep_is_valid(ep)); + + ep_ctrl = udd_ep_get_ctrl(ep); + return (udd_endpoint_is_stall(ep_ctrl)); +} + +bool udd_ep_set_halt(udd_ep_id_t ep) +{ + UDD_EP_t *ep_ctrl; + Assert(udd_ep_is_valid(ep)); + + ep_ctrl = udd_ep_get_ctrl(ep); + udd_endpoint_enable_stall(ep_ctrl); + udd_endpoint_clear_dtgl(ep_ctrl); + + udd_ep_abort(ep); + return true; +} + +bool udd_ep_clear_halt(udd_ep_id_t ep) +{ + udd_ep_job_t *ptr_job; + UDD_EP_t *ep_ctrl; + Assert(udd_ep_is_valid(ep)); + + ep_ctrl = udd_ep_get_ctrl(ep); + if (!udd_endpoint_is_stall(ep_ctrl)) { + return true; // No stall on going + } + udd_endpoint_disable_stall(ep_ctrl); + + // If a job is register on clear halt action + // then execute callback + ptr_job = udd_ep_get_job(ep); + if (ptr_job->busy == true) { + ptr_job->busy = false; + ptr_job->call_nohalt(); + } + return true; +} + +bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket, uint8_t * buf, + iram_size_t buf_size, udd_callback_trans_t callback) +{ + udd_ep_job_t *ptr_job; + irqflags_t flags; + UDD_EP_t *ep_ctrl; + + Assert(udd_ep_is_valid(ep)); + + // Get control & job about this endpoint + ptr_job = udd_ep_get_job(ep); + ep_ctrl = udd_ep_get_ctrl(ep); + + if (!udd_endpoint_is_enable(ep_ctrl)) { + return false; // Endpoint not allocated + } + if (udd_endpoint_get_type(ep_ctrl)!=USB_EP_TYPE_ISOCHRONOUS_gc + && udd_endpoint_is_stall(ep_ctrl)) { + return false; // Endpoint is halted + } + flags = cpu_irq_save(); + if (ptr_job->busy == true) { + cpu_irq_restore(flags); + return false; // Job already on going + } + ptr_job->busy = true; + cpu_irq_restore(flags); + + + // Update Job information + ptr_job->buf = buf; + ptr_job->buf_size = buf_size; + ptr_job->nb_trans = 0; + ptr_job->call_trans = callback; + // Need to enable shortpacket to send a ZLP (buf_size==0) + ptr_job->b_shortpacket = b_shortpacket || (buf_size==0); + ptr_job->b_use_out_cache_buffer = false; + + // Initialize value to simulate a empty transfer + if (USB_EP_DIR_IN == (ep & USB_EP_DIR_IN)) { + udd_endpoint_in_reset_nb_sent(ep_ctrl); + } + else + { + if ((USB_EP_TYPE_ISOCHRONOUS_gc == udd_endpoint_get_type(ep_ctrl)) + && (0 != (buf_size % udd_ep_get_size(ep_ctrl)))) { + // The user must use a buffer size modulo endpoint size + ptr_job->busy = false; + return false; + } + udd_endpoint_out_reset_nb_received(ep_ctrl); + udd_endpoint_out_set_nbbyte(ep_ctrl, 0); + } + // Request next transfer + udd_ep_trans_complet(ep); + return true; +} + +void udd_ep_abort(udd_ep_id_t ep) +{ + UDD_EP_t *ep_ctrl; + udd_ep_job_t *ptr_job; + Assert(udd_ep_is_valid(ep)); + + ep_ctrl = udd_ep_get_ctrl(ep); + ptr_job = udd_ep_get_job(ep); + + // Stop transfer + udd_endpoint_set_NACK0(ep_ctrl); + if (ptr_job->busy == false) { + return; // No job on going + } + ptr_job->busy = false; + if (NULL != ptr_job->call_trans) { + ptr_job->call_trans(UDD_EP_TRANSFER_ABORT, + (ep & USB_EP_DIR_IN) ? + udd_endpoint_in_nb_sent(ep_ctrl) + : udd_endpoint_out_nb_receiv(ep_ctrl), + ep); + } +} + +bool udd_ep_wait_stall_clear(udd_ep_id_t ep, + udd_callback_halt_cleared_t callback) +{ + udd_ep_job_t *ptr_job; + UDD_EP_t *ep_ctrl; + Assert(udd_ep_is_valid(ep)); + + ep_ctrl = udd_ep_get_ctrl(ep); + ptr_job = udd_ep_get_job(ep); + + if (udd_endpoint_is_stall(ep_ctrl)) { + // Wait clear halt endpoint + if (ptr_job->busy == true) { + return false; // Job already on going + } + ptr_job->busy = true; + ptr_job->call_nohalt = callback; + } else { + // endpoint not halted then call directly callback + callback(); + } + return true; +} +#endif // (0!=USB_DEVICE_MAX_EP) + +//-------------------------------------------------------- +//--- INTERNAL ROUTINES TO MANAGED GLOBAL EVENTS + +/** + * \internal + * \brief Function called by USB bus event interrupt + * + * USB bus event interrupt includes : + * - USB line events SOF, reset, suspend, resume, wakeup + * - endpoint control errors underflow, overflow, stall + */ +ISR(USB_BUSEVENT_vect) +{ + if (udd_is_start_of_frame_event()) { + udd_ack_start_of_frame_event(); + udc_sof_notify(); +#ifdef UDC_SOF_EVENT + UDC_SOF_EVENT(); +#endif + goto udd_interrupt_bus_event_end; + } + + if (udd_ctrl_interrupt_error()) { + goto udd_interrupt_bus_event_end; + } + if (udd_is_reset_event()) { + udd_ack_reset_event(); +#if (0!=USB_DEVICE_MAX_EP) + // Abort all endpoint jobs on going + uint8_t i; + for (i = 1; i < USB_DEVICE_MAX_EP; i++) { + udd_ep_abort(i); + udd_ep_abort(i | USB_EP_DIR_IN); + } +#endif + udc_reset(); + + // Reset USB address to 0 + udd_set_device_address(0); + // Alloc and configure control endpoint + udd_ep_init(0, USB_EP_TYPE_CONTROL, USB_DEVICE_EP_CTRL_SIZE); + udd_ep_init(0 | USB_EP_DIR_IN, USB_EP_TYPE_CONTROL, + USB_DEVICE_EP_CTRL_SIZE); + udd_control_out_set_buf(&udd_ctrl_buffer); + // Reset endpoint control management + udd_ctrl_init(); + goto udd_interrupt_bus_event_end; + } + + if (udd_is_suspend_event()) { + udd_ack_suspend_event(); + udd_sleep_mode(false); // Enter in SUSPEND mode +#ifdef UDC_SUSPEND_EVENT + UDC_SUSPEND_EVENT(); +#endif + goto udd_interrupt_bus_event_end; + } + + if (udd_is_resume_event()) { + udd_ack_resume_event(); + udd_sleep_mode(true); // Enter in power reduction mode +#ifdef UDC_RESUME_EVENT + UDC_RESUME_EVENT(); +#endif + goto udd_interrupt_bus_event_end; + } + +udd_interrupt_bus_event_end: + return; +} + +/** + * \internal + * \brief Function called by USB transfer complete interrupt + * + * USB transfer complete interrupt includes events about endpoint transfer on all endpoints. + */ +ISR(USB_TRNCOMPL_vect) +{ +#if (0!=USB_DEVICE_MAX_EP) + uint8_t ep_index; + uint8_t i_fifo; + uint16_t ad; + uint16_t *p_ad; + int8_t rp; + UDD_EP_t *ep_ctrl; + udd_ep_id_t ep; +#endif + + if (!udd_is_tc_event()) { + // If no other transfer complete + // then check reception of SETUP packet on control endpoint + if (udd_ctrl_interrupt_tc_setup()) { + // Interrupt acked by control endpoint managed + goto udd_interrupt_tc_end; + } + Assert(false); + } + // Check IN/OUT transfer complete on all endpoints + udd_ack_tc_event(); + +#if (0!=USB_DEVICE_MAX_EP) + //** Decode TC FIFO + // Compute ep addr + rp = udd_get_fifo_rp(); + i_fifo = 2 * (1 + ~rp); + ad = ((uint16_t) udd_sram.ep_ctrl) - i_fifo; + p_ad = (uint16_t *) ad; + // Compute ep + ep_index = (((uint16_t) * p_ad - ((uint16_t) udd_sram.ep_ctrl)) >> 3); + ep = (ep_index / 2) + ((ep_index & 1) ? USB_EP_DIR_IN : 0); + Assert(USB_DEVICE_MAX_EP >= (ep & USB_EP_ADDR_MASK)); + + // Ack IT TC of endpoint + ep_ctrl = udd_ep_get_ctrl(ep); + if (!udd_endpoint_transfer_complete(ep_ctrl)) { + return; // Error, TC is generated by Multipacket transfer + } + udd_endpoint_ack_transfer_complete(ep_ctrl); + + // Check status on control endpoint + if (ep == 0) { + udd_ctrl_out_received(); + goto udd_interrupt_tc_end; // Interrupt acked by control endpoint managed + } + if (ep == (0 | USB_EP_DIR_IN)) { + udd_ctrl_in_sent(); + goto udd_interrupt_tc_end; // Interrupt acked by control endpoint managed + } + Assert(udd_ep_is_valid(ep)); + // Manage end of transfer on endpoint bulk/interrupt/isochronous + udd_ep_trans_complet(ep); + +#else + + udd_get_fifo_rp(); + if (udd_endpoint_transfer_complete(udd_ep_get_ctrl(0))) { + udd_endpoint_ack_transfer_complete(udd_ep_get_ctrl(0)); + udd_ctrl_out_received(); + }else{ + udd_endpoint_ack_transfer_complete(udd_ep_get_ctrl(0 | USB_EP_DIR_IN)); + udd_ctrl_in_sent(); + } +#endif + +udd_interrupt_tc_end: + return; +} + +//-------------------------------------------------------- +//--- INTERNAL ROUTINES TO INITIALIZE ENDPOINT + +static void udd_ep_init(udd_ep_id_t ep, uint8_t bmAttributes, + uint16_t MaxEndpointSize) +{ + USB_EP_TYPE_t type; + USB_EP_BUFSIZE_t size; + UDD_EP_t *ep_ctrl; + +#if (0!=USB_DEVICE_MAX_EP) + // Translate USB attribute to hardware defines + switch (bmAttributes & USB_EP_TYPE_MASK) { + case USB_EP_TYPE_CONTROL: + type = USB_EP_TYPE_CONTROL_gc; + break; + case USB_EP_TYPE_ISOCHRONOUS: + type = USB_EP_TYPE_ISOCHRONOUS_gc; + break; + case USB_EP_TYPE_BULK: + case USB_EP_TYPE_INTERRUPT: //interrupt behaves as bulk + type = USB_EP_TYPE_BULK_gc; + break; + default: + Assert(false); // Wrong value + break; + } +#else + type = USB_EP_TYPE_CONTROL_gc; +#endif + + // Translate USB endpoint size to hardware defines + switch (MaxEndpointSize) { + default: + Assert(false); // Wrong value + case 8: + size = USB_EP_BUFSIZE_8_gc; + break; + case 16: + size = USB_EP_BUFSIZE_16_gc; + break; + case 32: + size = USB_EP_BUFSIZE_32_gc; + break; + case 64: + size = USB_EP_BUFSIZE_64_gc; + break; +#if (0!=USB_DEVICE_MAX_EP) + case 128: + size = USB_EP_BUFSIZE_128_gc; + break; + case 256: + size = USB_EP_BUFSIZE_256_gc; + break; + case 512: + size = USB_EP_BUFSIZE_512_gc; + break; + case 1023: + size =USB_EP_BUFSIZE_1023_gc; + break; +#endif + } + + // Enable endpoint + ep_ctrl = udd_ep_get_ctrl(ep); + udd_endpoint_disable(ep_ctrl); + udd_endpoint_clear_status(ep_ctrl); + udd_endpoint_set_control(ep_ctrl, (uint8_t) type | (uint8_t) size); +} + +static UDD_EP_t *udd_ep_get_ctrl(udd_ep_id_t ep) +{ + return &udd_sram.ep_ctrl[(2 * (ep & USB_EP_ADDR_MASK) + + ((ep & USB_EP_DIR_IN) ? 1 : 0))]; +} + + +//-------------------------------------------------------- +//--- INTERNAL ROUTINES TO MANAGED THE CONTROL ENDPOINT + +static void udd_ctrl_init(void) +{ + udd_disable_overflow_interrupt(); + udd_disable_underflow_interrupt(); + + // Clear status flag from control endpoints + // Mandatory for ATxmega128A1 Rev. K + udd_control_in_set_NACK0(); + udd_control_in_set_bytecnt(0); + udd_control_in_ack_tc(); + udd_control_ack_in_underflow(); + udd_control_out_ack_tc(); + udd_control_ack_out_overflow(); + + udd_g_ctrlreq.callback = NULL; + udd_g_ctrlreq.over_under_run = NULL; + udd_g_ctrlreq.payload_size = 0; + udd_ep_control_state = UDD_EPCTRL_SETUP; +} + +static void udd_ctrl_setup_received(void) +{ + if (UDD_EPCTRL_SETUP != udd_ep_control_state) { + if ((UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP == udd_ep_control_state) + || (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state)) { + // Accept that ZLP event can be hidden by setup packet event + // in case of setup packet sending quickly after a ZLP + udd_ctrl_endofrequest(); + } + // Reinitializes control endpoint management + udd_ctrl_init(); + } + // Fill setup request structure + if (8 != udd_control_out_get_bytecnt()) + return; // Error data number don't correspond to SETUP packet + memcpy((uint8_t *) & udd_g_ctrlreq.req, udd_ctrl_buffer, 8); + + // To detect a protocol error on setup, enable nak interrupt on IN/OUT of control endpoint + udd_enable_overflow_interrupt(); + udd_enable_underflow_interrupt(); + + // Decode setup request + if (udc_process_setup() == false) { + // Setup request unknown then stall it + udd_ctrl_stall_data(); + return; + } + + if (Udd_setup_is_in()) { + udd_ctrl_prev_payload_nb_trans = 0; + udd_ctrl_payload_nb_trans = 0; + udd_ep_control_state = UDD_EPCTRL_DATA_IN; + udd_ctrl_in_sent(); // Send first data transfer + } else { + if (0 == udd_g_ctrlreq.req.wLength) { + // No data phase requested + // Send IN ZLP to ACK setup request + udd_ctrl_send_zlp_in(); + return; + } + // OUT data phase requested + udd_ctrl_prev_payload_nb_trans = 0; + udd_ctrl_payload_nb_trans = 0; + udd_ep_control_state = UDD_EPCTRL_DATA_OUT; + // Clear packet to receive first packet + udd_control_out_clear_NACK0(); + } +} + +static void udd_ctrl_in_sent(void) +{ + static bool b_shortpacket = false; + uint16_t nb_remain; + + if (UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP == udd_ep_control_state) { + // ZLP on IN is sent, then valid end of setup request + udd_ctrl_endofrequest(); + // Reinitializes control endpoint management + udd_ctrl_init(); + return; + } + Assert(udd_ep_control_state == UDD_EPCTRL_DATA_IN); + + nb_remain = udd_g_ctrlreq.payload_size - udd_ctrl_payload_nb_trans; + if (0 == nb_remain) { + // Update number of total data sending by previous playload buffer + udd_ctrl_prev_payload_nb_trans += udd_ctrl_payload_nb_trans; + if ((udd_g_ctrlreq.req.wLength == udd_ctrl_prev_payload_nb_trans) + || b_shortpacket) { + // All data requested are transfered or a short packet has been sent + // then it is the end of data phase. + // Generate an OUT ZLP for handshake phase. + udd_ctrl_send_zlp_out(); + return; + } + // Need of new buffer because the data phase is not complete + if ((!udd_g_ctrlreq.over_under_run) + || (!udd_g_ctrlreq.over_under_run())) { + // Underrun then send zlp on IN + // nb_remain == 0 allows to send a IN ZLP + } else { + // A new payload buffer is given + udd_ctrl_payload_nb_trans = 0; + nb_remain = udd_g_ctrlreq.payload_size; + } + } + // Continue transfer an send next data + if (nb_remain >= USB_DEVICE_EP_CTRL_SIZE) { + nb_remain = USB_DEVICE_EP_CTRL_SIZE; + b_shortpacket = false; + } else { + b_shortpacket = true; + } + udd_control_in_set_bytecnt(nb_remain); + + // Link payload buffer directly on USB hardware + udd_control_in_set_buf(udd_g_ctrlreq.payload + udd_ctrl_payload_nb_trans); + udd_ctrl_payload_nb_trans += nb_remain; + + // Valid and sent the data available in control endpoint buffer + udd_control_in_clear_NACK0(); +} + +static void udd_ctrl_out_received(void) +{ + uint16_t nb_data; + + if (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state) { + // Valid end of setup request + udd_ctrl_endofrequest(); + // Reinitializes control endpoint management + udd_ctrl_init(); + return; + } + Assert(udd_ep_control_state == UDD_EPCTRL_DATA_OUT); + + // Read data received during OUT phase + nb_data = udd_control_out_get_bytecnt(); + + if (udd_g_ctrlreq.payload_size < (udd_ctrl_payload_nb_trans + nb_data)) { + // Payload buffer too small, ignore data remaining + nb_data = udd_g_ctrlreq.payload_size - udd_ctrl_payload_nb_trans; + } + + memcpy((uint8_t *) (udd_g_ctrlreq.payload + udd_ctrl_payload_nb_trans), + udd_ctrl_buffer, nb_data); + udd_ctrl_payload_nb_trans += nb_data; + + if ((USB_DEVICE_EP_CTRL_SIZE != nb_data) || (udd_g_ctrlreq.req.wLength + <= (udd_ctrl_prev_payload_nb_trans + + udd_ctrl_payload_nb_trans))) { + // End of reception because it is a short packet + // or all data are transfered + + // Before send ZLP, call intermediate callback + // in case of data receive generate a stall + udd_g_ctrlreq.payload_size = udd_ctrl_payload_nb_trans; + if (NULL != udd_g_ctrlreq.over_under_run) { + if (!udd_g_ctrlreq.over_under_run()) { + // Stall ZLP + udd_ctrl_stall_data(); + return; + } + } + // Send IN ZLP to ACK setup request + udd_ctrl_send_zlp_in(); + return; + } + + if (udd_g_ctrlreq.payload_size == udd_ctrl_payload_nb_trans) { + // Overrun then request a new payload buffer + if (!udd_g_ctrlreq.over_under_run) { + // No callback available to request a new payload buffer + udd_ctrl_stall_data(); + return; + } + if (!udd_g_ctrlreq.over_under_run()) { + // No new payload buffer delivered + udd_ctrl_stall_data(); + return; + } + // New payload buffer available + // Update number of total data received + udd_ctrl_prev_payload_nb_trans += udd_ctrl_payload_nb_trans; + // Reinit reception on payload buffer + udd_ctrl_payload_nb_trans = 0; + } + // Free buffer of OUT control endpoint to authorize next reception + udd_control_out_clear_NACK0(); +} + +static void udd_ctrl_underflow(void) +{ + if (udd_is_tc_event() || udd_ctrl_interrupt_tc_setup()) { + return; // underflow ignored if a transfer complete has been no processed + } + if (UDD_EPCTRL_DATA_OUT == udd_ep_control_state) { + // Host want to stop OUT transaction + // then stop to wait OUT data phase and wait IN ZLP handshake + udd_ctrl_send_zlp_in(); + } else if (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state) { + // A OUT handshake is waiting by device, + // but host want extra IN data then stall extra IN data and following status stage + udd_control_in_enable_stall(); + udd_control_out_enable_stall(); + } +} + +static void udd_ctrl_overflow(void) +{ + if (udd_is_tc_event() || udd_ctrl_interrupt_tc_setup()) { + return; // overflow ignored if a transfer complete has been no processed + } + if (UDD_EPCTRL_DATA_IN == udd_ep_control_state) { + // Host want to stop IN transaction + // then stop to wait IN data phase and wait OUT ZLP handshake + udd_ctrl_send_zlp_out(); + } else if (UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP == udd_ep_control_state) { + // A IN handshake is waiting by device, + // but host want extra OUT data then stall extra OUT data and following status stage + udd_control_in_enable_stall(); + udd_control_out_enable_stall(); + } +} + +static void udd_ctrl_stall_data(void) +{ + // Stall all packets on IN & OUT control endpoint + udd_ep_control_state = UDD_EPCTRL_STALL_REQ; + udd_control_in_enable_stall(); + udd_control_out_enable_stall(); +} + +static void udd_ctrl_send_zlp_in(void) +{ + udd_ep_control_state = UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP; + // Valid and sent empty IN packet on control endpoint + udd_control_in_set_bytecnt(0); + udd_control_in_clear_NACK0(); +} + +static void udd_ctrl_send_zlp_out(void) +{ + udd_ep_control_state = UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP; + // Valid reception of OUT packet on control endpoint + udd_control_out_clear_NACK0(); +} + +static void udd_ctrl_endofrequest(void) +{ + // If a callback is registered then call it + if (udd_g_ctrlreq.callback) { + udd_g_ctrlreq.callback(); + } +} + +static bool udd_ctrl_interrupt_error(void) +{ + // Underflow only managed for control endpoint + if (udd_is_underflow_event()) { + udd_ack_underflow_event(); + if (udd_control_in_underflow()) { + udd_ctrl_underflow(); + } + return true; + } + // Overflow only managed for control endpoint + if (udd_is_overflow_event()) { + udd_ack_overflow_event(); + if (udd_control_out_overflow()) { + udd_ctrl_overflow(); + } + return true; + } + return false; +} + +static bool udd_ctrl_interrupt_tc_setup(void) +{ + if (!udd_is_setup_event()) { + return false; + } + udd_ack_setup_event(); + + // Clear eventually previous stall events + udd_control_out_ack_stall(); + udd_control_in_ack_stall(); + udd_ack_stall_event(); + + Assert(udd_control_setup()); // A setup must be received on control endpoint + + // Ack SETUP packet and decode request + udd_control_ack_setup(); + udd_ctrl_setup_received(); + return true; +} + + +//-------------------------------------------------------- +//--- INTERNAL ROUTINES TO MANAGED THE BULK/INTERRUPT/ISOCHRONOUS ENDPOINTS + +#if (0!=USB_DEVICE_MAX_EP) + +static uint16_t udd_ep_get_size(UDD_EP_t * ep_ctrl) +{ + // Translate hardware defines to USB endpoint size + switch (udd_endpoint_get_size_field(ep_ctrl)) { + default: + case USB_EP_BUFSIZE_8_gc: + return 8; + case USB_EP_BUFSIZE_16_gc: + return 16; + case USB_EP_BUFSIZE_32_gc: + return 32; + case USB_EP_BUFSIZE_64_gc: + return 64; + case USB_EP_BUFSIZE_128_gc: + return 128; + case USB_EP_BUFSIZE_256_gc: + return 256; + case USB_EP_BUFSIZE_512_gc: + return 512; + case USB_EP_BUFSIZE_1023_gc: + return 1023; + } +} + +static udd_ep_job_t *udd_ep_get_job(udd_ep_id_t ep) +{ + return &udd_ep_job[(2 * (ep & USB_EP_ADDR_MASK) + + ((ep & USB_EP_DIR_IN) ? 1 : 0)) - 2]; +} + +bool udd_ep_is_valid(udd_ep_id_t ep) +{ + ep &= USB_EP_ADDR_MASK; + if (ep == 0) { + return false; + } + return (USB_DEVICE_MAX_EP >= ep); +} + +static void udd_ep_trans_complet(udd_ep_id_t ep) +{ + UDD_EP_t *ep_ctrl; + udd_ep_job_t *ptr_job; + uint16_t ep_size, nb_trans; + iram_size_t next_trans; + + ptr_job = udd_ep_get_job(ep); + ep_ctrl = udd_ep_get_ctrl(ep); + ep_size = udd_ep_get_size(ep_ctrl); + + if (USB_EP_DIR_IN == (ep & USB_EP_DIR_IN)) { + // Transfer complete on IN + nb_trans = udd_endpoint_in_nb_sent(ep_ctrl); + + // Update number of data transfered + ptr_job->nb_trans += nb_trans; + + // Need to send other data + if (ptr_job->nb_trans != ptr_job->buf_size) { + next_trans = ptr_job->buf_size - ptr_job->nb_trans; + if (UDD_ENDPOINT_MAX_TRANS < next_trans) { + // The USB hardware support a maximum + // transfer size of UDD_ENDPOINT_MAX_TRANS Bytes + next_trans = UDD_ENDPOINT_MAX_TRANS - + (UDD_ENDPOINT_MAX_TRANS % ep_size); + } + // Need ZLP, if requested and last packet is not a short packet + ptr_job->b_shortpacket = ptr_job->b_shortpacket + && (0==(next_trans % ep_size)); + udd_endpoint_in_reset_nb_sent(ep_ctrl); + udd_endpoint_in_set_bytecnt(ep_ctrl, next_trans); + // Link the user buffer directly on USB hardware DMA + udd_endpoint_set_buf(ep_ctrl, &ptr_job->buf[ptr_job->nb_trans]); + udd_endpoint_clear_NACK0(ep_ctrl); + return; + } + + // Need to send a ZLP after all data transfer + if (ptr_job->b_shortpacket) { + ptr_job->b_shortpacket = false; + udd_endpoint_in_reset_nb_sent(ep_ctrl); + udd_endpoint_in_set_bytecnt(ep_ctrl, 0); + udd_endpoint_clear_NACK0(ep_ctrl); + return; + } + } + else + { + // Transfer complete on OUT + nb_trans = udd_endpoint_out_nb_receiv(ep_ctrl); + + // Can be necessary to copy data receive from cache buffer to user buffer + if (ptr_job->b_use_out_cache_buffer) { + memcpy(&ptr_job->buf[ptr_job->nb_trans] + , udd_ep_out_cache_buffer[ep - 1] + , ptr_job->buf_size % ep_size); + } + + // Update number of data transfered + ptr_job->nb_trans += nb_trans; + if (ptr_job->nb_trans > ptr_job->buf_size) { + ptr_job->nb_trans = ptr_job->buf_size; + } + + // If all previous data requested are received and user buffer not full + // then need to receive other data + if ((nb_trans == udd_endpoint_out_get_nbbyte_requested(ep_ctrl)) + && (ptr_job->nb_trans != ptr_job->buf_size)) { + next_trans = ptr_job->buf_size - ptr_job->nb_trans; + if (UDD_ENDPOINT_MAX_TRANS < next_trans) { + // The USB hardware support a maximum transfer size + // of UDD_ENDPOINT_MAX_TRANS Bytes + next_trans = UDD_ENDPOINT_MAX_TRANS + - (UDD_ENDPOINT_MAX_TRANS % ep_size); + } else { + next_trans -= next_trans % ep_size; + } + + udd_endpoint_out_reset_nb_received(ep_ctrl); + if (next_trans < ep_size) { + // Use the cache buffer for Bulk or Interrupt size endpoint + ptr_job->b_use_out_cache_buffer = true; + udd_endpoint_set_buf( ep_ctrl, + udd_ep_out_cache_buffer[ep - 1]); + udd_endpoint_out_set_nbbyte(ep_ctrl, ep_size); + } else { + // Link the user buffer directly on USB hardware DMA + udd_endpoint_set_buf(ep_ctrl, &ptr_job->buf[ptr_job->nb_trans]); + udd_endpoint_out_set_nbbyte(ep_ctrl, next_trans); + } + // Start transfer + udd_endpoint_clear_NACK0(ep_ctrl); + return; + } + } + + // Job complete then call callback + if (ptr_job->busy) { + ptr_job->busy = false; + if (NULL != ptr_job->call_trans) { + ptr_job->call_trans(UDD_EP_TRANSFER_OK, + ptr_job->nb_trans, + ep); + } + } + return; +} +#endif // (0!=USB_DEVICE_MAX_EP) +//@} diff --git a/DSTAT-temp/src/asf/xmega/drivers/usb/usb_device.h b/DSTAT-temp/src/asf/xmega/drivers/usb/usb_device.h new file mode 100644 index 0000000..6a9afbf --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/drivers/usb/usb_device.h @@ -0,0 +1,387 @@ +/** + * \file + * + * \brief USB Driver header file for XMEGA products including USB interface. + * + * Copyright (c) 2011-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _USB_DEVICE_H_ +#define _USB_DEVICE_H_ + +#include + +/** + * \ingroup udd_group + * \defgroup udd_xmega_usb_group Xmega USB Device Driver + * USBC low-level driver for USB Device mode + * + * + * @{ + */ + +//! @name USB Device main management +//! @{ + +/** + * \brief Initializes the USB DP/DM buffers + * + * This functions initializes the USB buffer using the calibration value + * stored in production raw. + * If the calibration value is not found (0xFF) value, a default typical + * value is applied. + * Alternatively user can force calibration values using USB_PAD_USER_CAL0 + * and USB_PAD_USER_CAL1 + * + */ +static inline void usb_pad_init(void) +{ + uint8_t cal; + +#ifdef USB_PAD_USER_CAL0 + USB_CAL0 = USB_PAD_USER_CAL0; +#else + cal = nvm_read_production_signature_row + (nvm_get_production_signature_row_offset(USBCAL0)); + if (cal != 0xFF) { + USB_CAL0 = cal; + } else { + USB_CAL0 = 0x1F; + } +#endif + +#ifdef USB_PAD_USER_CAL1 + USB_CAL1 = USB_PAD_USER_CAL1; +#else + cal = nvm_read_production_signature_row + (nvm_get_production_signature_row_offset(USBCAL1)); + if (cal != 0xFF) { + USB_CAL1 = cal; + } else { + USB_CAL1 = 0x1F; + } +#endif +} + +#define udd_enable_interface() (USB_CTRLA |= USB_ENABLE_bm) +#define udd_disable_interface() (USB_CTRLA &= ~USB_ENABLE_bm) +#define udd_attach_device() (USB_CTRLB |= USB_ATTACH_bm) +#define udd_detach_device() (USB_CTRLB &= ~USB_ATTACH_bm) +#define udd_gnak_disable() (USB_CTRLB &= ~USB_GNACK_bm) +#define udd_gnak_enable() (USB_CTRLB |= USB_GNACK_bm) +#define udd_gnak_is_enable() (USB_CTRLB & USB_GNACK_bm) +#define udd_set_nb_max_ep(n) (USB_CTRLA |= n) +#define udd_enable_store_frame_number() (USB_CTRLA |= USB_STFRNUM_bm) +#define udd_disable_store_frame_number() (USB_CTRLA &= ~USB_STFRNUM_bm) +#define udd_set_full_speed() (USB_CTRLA |= USB_SPEED_bm) +#define udd_set_low_speed() (USB_CTRLA &= ~USB_SPEED_bm) +#define udd_set_ep_table_addr(n) (USB.EPPTR = (uint16_t)n) +#define udd_get_ep_table_addr() (USB.EPPTR) +#define udd_get_fifo_rp() (USB_FIFORP) +#define udd_reset_fifo() (USB_FIFORP=0xFF) +#define udd_enable_interrupt(level) (USB_INTCTRLA |= level&(USB_INTLVL1_bm|USB_INTLVL0_bm)) + +#define udd_set_device_address(n) (USB_ADDR=n) +#define udd_get_device_address() (USB_ADDR) +#define udd_enable_fifo() (USB_CTRLA |= USB_FIFOEN_bm) +#define udd_disable_fifo() (USB_CTRLA &= ~USB_FIFOEN_bm) + +#define udd_send_remote_wake_up() (USB_CTRLB &= ~USB_RWAKEUP_bm, USB_CTRLB |= USB_RWAKEUP_bm) +#define udd_set_global_nack() (USB_CTRLB |= USB_GNACK_bm) +#define udd_is_crc_event() (USB_INTFLAGSASET & USB_CRCIF_bm ? true : false) +#define udd_ack_crc_event() (USB_INTFLAGSACLR = USB_CRCIF_bm) +#define udd_set_crc_event() (USB_INTFLAGSASET = USB_CRCIF_bm) +#define udd_enable_crc_interrupt() (USB_INTCTRLA |= USB_CRCIE_bm) +#define udd_disable_crc_interrupt() (USB_INTCTRLA &= ~USB_CRCIE_bm) + +#define udd_is_start_of_frame_event() (USB_INTFLAGSASET & USB_SOFIF_bm ? true : false) +#define udd_ack_start_of_frame_event() (USB_INTFLAGSACLR = USB_SOFIF_bm) +#define udd_set_start_of_frame_event() (USB_INTFLAGSASET = USB_SOFIF_bm) +#define udd_enable_start_of_frame_interrupt() (USB_INTCTRLA |= USB_SOFIE_bm) +#define udd_disable_start_of_frame_interrupt() (USB_INTCTRLA &= ~USB_SOFIE_bm) +#define udd_is_enable_start_of_frame_interrupt() (0!=(USB_INTCTRLA|USB_SOFIE_bm)) + +#define udd_is_reset_event() (USB_INTFLAGSASET & USB_RSTIF_bm ? true : false) +#define udd_ack_reset_event() (USB_INTFLAGSACLR = USB_RSTIF_bm) +#define udd_set_reset_event() (USB_INTFLAGSASET = USB_RSTIF_bm) + +#define udd_is_suspend_event() (USB_INTFLAGSASET & USB_SUSPENDIF_bm ? true : false) +#define udd_ack_suspend_event() (USB_INTFLAGSACLR = USB_SUSPENDIF_bm) +#define udd_set_suspend_event() (USB_INTFLAGSASET = USB_SUSPENDIF_bm) + +#define udd_is_resume_event() (USB_INTFLAGSASET & USB_RESUMEIF_bm ? true : false) +#define udd_ack_resume_event() (USB_INTFLAGSACLR = USB_RESUMEIF_bm) +#define udd_set_resume_event() (USB_INTFLAGSASET = USB_RESUMEIF_bm) + +#define udd_enable_busevt_interrupt() (USB_INTCTRLA |= USB_BUSEVIE_bm) +#define udd_disable_busevt_interrupt() (USB_INTCTRLA &= ~USB_BUSEVIE_bm) + +#define udd_is_setup_event() (USB_INTFLAGSBCLR & USB_SETUPIF_bm ? true : false) +#define udd_ack_setup_event() (USB_INTFLAGSBCLR = USB_SETUPIF_bm) +#define udd_set_setup_event() (USB_INTFLAGSBSET = USB_SETUPIF_bm) +#define udd_enable_setup_interrupt() (USB_INTCTRLB |= USB_SETUPIE_bm) +#define udd_disable_setup_interrupt() (USB_INTCTRLB &= ~USB_SETUPIE_bm) + +#define udd_is_tc_event() (USB_INTFLAGSBCLR & USB_TRNIF_bm ? true : false) +#define udd_ack_tc_event() (USB_INTFLAGSBCLR = USB_TRNIF_bm) +#define udd_set_tc_event() (USB_INTFLAGSBSET = USB_TRNIF_bm) +#define udd_enable_tc_interrupt() (USB_INTCTRLB |= USB_TRNIE_bm) +#define udd_disable_tc_interrupt() (USB_INTCTRLB &= ~USB_TRNIE_bm) + +#define udd_is_overflow_event() (USB_INTFLAGSASET & USB_OVFIF_bm ? true : false) +#define udd_ack_overflow_event() (USB_INTFLAGSACLR = USB_OVFIF_bm) +#define udd_set_overflow_event() (USB_INTFLAGSASET = USB_OVFIF_bm) +#define udd_enable_overflow_interrupt() (USB_INTCTRLA |= USB_BUSERRIE_bm) +#define udd_disable_overflow_interrupt() (USB_INTCTRLA &= ~USB_BUSERRIE_bm) +#define udd_is_enable_overflow_interrupt() (USB_INTCTRLA&USB_BUSERRIE_bm ? true : false) + +#define udd_is_underflow_event() (USB_INTFLAGSASET & USB_UNFIF_bm ? true : false) +#define udd_ack_underflow_event() (USB_INTFLAGSACLR = USB_UNFIF_bm) +#define udd_set_underflow_event() (USB_INTFLAGSASET = USB_UNFIF_bm) +#define udd_enable_underflow_interrupt() (USB_INTCTRLA |= USB_BUSERRIE_bm) +#define udd_disable_underflow_interrupt() (USB_INTCTRLA &= ~USB_BUSERRIE_bm) +#define udd_is_enable_underflow_interrupt() (USB_INTCTRLA&USB_BUSERRIE_bm ? true : false) + +#define udd_is_stall_event() (USB_INTFLAGSASET & USB_STALLIF_bm ? true : false) +#define udd_ack_stall_event() (USB_INTFLAGSACLR = USB_STALLIF_bm) +#define udd_set_stall_event() (USB_INTFLAGSASET = USB_STALLIF_bm) +#define udd_enable_stall_interrupt() (USB_INTCTRLA |= USB_STALLIE_bm) +#define udd_disable_stall_interrupt() (USB_INTCTRLA &= ~USB_STALLIE_bm) +#define udd_is_enable_stall_interrupt() (USB_INTCTRLA&USB_STALLIE_bm ? true : false) +//! @} + +//! @name USB Device read/modify/write management +//! @{ +#ifndef USB_WORKAROUND_DO_NOT_USE_RMW +/* + * Read modify write new instructions for Xmega + * inline asm implementation with R16 register. + * This should be removed later on when the new instructions + * will be available within the compiler. + * + */ +// Load and Clear +#ifdef __GNUC__ +#define LACR16(addr,msk) \ + __asm__ __volatile__ ( \ + "ldi r16, %1" "\n\t" \ + ".dc.w 0x9306" "\n\t"\ + ::"z" (addr), "M" (msk):"r16") +#else +#define LACR16(addr,msk) __lac((unsigned char)msk,(unsigned char*)addr) +#endif + +// Load and Set +#ifdef __GNUC__ +#define LASR16(addr,msk) \ + __asm__ __volatile__ ( \ + "ldi r16, %1" "\n\t" \ + ".dc.w 0x9305" "\n\t"\ + ::"z" (addr), "M" (msk):"r16") +#else +#define LASR16(addr,msk) __las((unsigned char)msk,(unsigned char*)addr) +#endif + +// Exchange +#ifdef __GNUC__ +#define XCHR16(addr,msk) \ + __asm__ __volatile__ ( \ + "ldi r16, %1" "\n\t" \ + ".dc.w 0x9304" "\n\t"\ + ::"z" (addr), "M" (msk):"r16") +#else +#define XCHR16(addr,msk) __xch(msk,addr) +#endif + +// Load and toggle +#ifdef __GNUC__ +#define LATR16(addr,msk) \ + __asm__ __volatile__ ( \ + "ldi r16, %1" "\n\t" \ + ".dc.w 0x9307" "\n\t"\ + ::"z" (addr), "M" (msk):"r16") +#else +#define LATR16(addr,msk) __lat(msk,addr) +#endif + +#else + +// Load and Clear +#define LACR16(addr,msk) (*addr &= ~msk) +// Load and Set +#define LASR16(addr,msk)(*addr |= msk) + +#endif +//! @} + + +//! @name USB Device endpoints table management +//! @{ + +#define udd_endpoint_set_control(ep_ctrl,val) (ep_ctrl->CTRL=val) +#define udd_endpoint_get_control(ep_ctrl) (ep_ctrl->CTRL) + +#define udd_endpoint_disable(ep_ctrl) udd_endpoint_set_control(ep_ctrl,0) +#define udd_endpoint_is_enable(ep_ctrl) (USB_EP_TYPE_DISABLE_gc!=udd_endpoint_get_type(ep_ctrl)) + + +#define udd_endpoint_enable_stall(ep_ctrl) (ep_ctrl->CTRL |= USB_EP_STALL_bm) +#define udd_endpoint_disable_stall(ep_ctrl) (ep_ctrl->CTRL &= ~USB_EP_STALL_bm) +#define udd_endpoint_is_stall(ep_ctrl) (ep_ctrl->CTRL &USB_EP_STALL_bm ? true : false) +#define udd_endpoint_set_multipacket(ep_ctrl) (ep_ctrl->CTRL |= USB_EP_MULTIPKT_bm) +#define udd_endpoint_TC_int_disable(ep_ctrl) (ep_ctrl->CTRL |= USB_EP_INTDSBL_bm) +#define udd_endpoint_set_pingpong(ep_ctrl) (ep_ctrl->CTRL |= USB_EP_PINGPONG_bm) +#define udd_endpoint_get_size_field(ep_ctrl) (ep_ctrl->CTRL & USB_EP_BUFSIZE_gm) +#define udd_endpoint_get_type(ep_ctrl) (ep_ctrl->CTRL & USB_EP_TYPE_gm) + +#define udd_endpoint_get_status(ep_ctrl) (ep_ctrl->STATUS) +#define udd_endpoint_clear_status(ep_ctrl) (ep_ctrl->STATUS=USB_EP_BUSNACK0_bm|USB_EP_BUSNACK1_bm) + +#define udd_endpoint_setup_received(ep_ctrl) (ep_ctrl->STATUS&USB_EP_SETUP_bm ? true : false) +#define udd_endpoint_ack_setup_received(ep_ctrl) LACR16(&ep_ctrl->STATUS, USB_EP_SETUP_bm) + +#define udd_endpoint_transfer_complete(ep_ctrl) (ep_ctrl->STATUS&USB_EP_TRNCOMPL0_bm ? true : false) +#define udd_endpoint_ack_transfer_complete(ep_ctrl) LACR16(&(ep_ctrl->STATUS), USB_EP_TRNCOMPL0_bm) +#define udd_endpoint_transfer_complete_bank0(ep_ctrl) (ep_ctrl->STATUS&USB_EP_TRNCOMPL0_bm ? true : false) +#define udd_endpoint_ack_transfer_complete_bankO(ep_ctrl) LACR16(&ep_ctrl->STATUS, USB_EP_TRNCOMPL0_bm) +#define udd_endpoint_transfer_complete_bank1(ep_ctrl) (ep_ctrl->STATUS&USB_EP_SETUP_bm ? true : false) +#define udd_endpoint_ack_transfer_complete_bank1(ep_ctrl) LACR16(&ep_ctrl->STATUS, USB_EP_SETUP_bm) + +#define udd_endpoint_get_bank(ep_ctrl) (ep_ctrl->STATUS & USB_EP_BANK_bm ? true : false) +#define udd_endpoint_set_bank(ep_ctrl) LASR16(&ep_ctrl->STATUS, USB_EP_BANK_bm) +#define udd_endpoint_clear_bank(ep_ctrl) LACR16(&ep_ctrl->STATUS, USB_EP_BANK_bm) + +#define udd_endpoint_set_dtgl(ep_ctrl) LASR16(&ep_ctrl->STATUS,USB_EP_TOGGLE_bm) +#define udd_endpoint_clear_dtgl(ep_ctrl) LACR16(&ep_ctrl->STATUS, USB_EP_TOGGLE_bm ) +#define udd_endpoint_get_dtgl(ep_ctrl) ((ep_ctrl->STATUS)&USB_EP_TOGGLE_bm ? true : false) +#define udd_endpoint_toggle_dtgl(ep_ctrl) LATR16(&ep_ctrl->STATUS, USB_EP_TOGGLE_bm) + +#define udd_endpoint_set_NACK0(ep_ctrl) LASR16(&ep_ctrl->STATUS,USB_EP_BUSNACK0_bm) +#define udd_endpoint_set_NACK1(ep_ctrl) LASR16(&ep_ctrl->STATUS,USB_EP_BUSNACK1_bm) +#define udd_endpoint_clear_NACK0(ep_ctrl) LACR16(&ep_ctrl->STATUS, USB_EP_BUSNACK0_bm) +#define udd_endpoint_clear_NACK1(ep_ctrl) LACR16(&ep_ctrl->STATUS, USB_EP_BUSNACK1_bm) +#define udd_endpoint_get_NACK1(ep_ctrl) ((ep_ctrl->STATUS&USB_EP_BUSNACK1_bm) ? true : false) +#define udd_endpoint_get_NACK0(ep_ctrl) ((ep_ctrl->STATUS&USB_EP_BUSNACK0_bm) ? true : false) +#define udd_endpoint_overflow(ep_ctrl) (ep_ctrl->STATUS&USB_EP_OVF_bm ? true : false) +#define udd_endpoint_underflow(ep_ctrl) (ep_ctrl->STATUS&USB_EP_UNF_bm ? true : false) + +#define UDD_ENDPOINT_MAX_TRANS (0x3FF) + +#define udd_endpoint_out_nb_receiv(ep_ctrl) (ep_ctrl->CNT) +#define udd_endpoint_out_reset_nb_received(ep_ctrl) (ep_ctrl->CNT = 0) +#define udd_endpoint_in_set_bytecnt(ep_ctrl,n) (ep_ctrl->CNT = n) +#define udd_endpoint_set_azlp(ep_ctrl) (ep_ctrl->CNT |= 0x8000) +#define udd_endpoint_clear_azlp(ep_ctrl) (ep_ctrl->CNT &= ~0x8000) + +#define udd_endpoint_set_buf(ep_ctrl,buf) (ep_ctrl->DATAPTR = (uint16_t) buf) + +#define udd_endpoint_in_nb_sent(ep_ctrl) (ep_ctrl->AUXDATA) +#define udd_endpoint_in_reset_nb_sent(ep_ctrl) (ep_ctrl->AUXDATA = 0) +#define udd_endpoint_out_set_nbbyte(ep_ctrl,nb) (ep_ctrl->AUXDATA = nb) +#define udd_endpoint_out_get_nbbyte_requested(ep_ctrl) (ep_ctrl->AUXDATA) +#define udd_endpoint_set_aux(ep_ctrl,buf) (ep_ctrl->AUXDATA = (uint16_t) buf) +//! @} + + +//! @name USB Device endpoint control field management +//! @{ + +//! @name USB Device endpoint control setup field management +//! @{ +#define udd_control_setup() (udd_sram.ep_ctrl[0].STATUS&USB_EP_SETUP_bm ? true : false) +#define udd_control_ack_setup() LACR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_SETUP_bm) +//! @} + +//! @name USB Device endpoint control OUT field management +//! @{ +#define udd_control_out_is_enable_stall() (udd_sram.ep_ctrl[0].CTRL&USB_EP_STALL_bm ? true : false) +#define udd_control_out_enable_stall() LASR16(&udd_sram.ep_ctrl[0].CTRL,USB_EP_STALL_bm) +#define udd_control_out_disable_stall() LACR16(&udd_sram.ep_ctrl[0].CTRL,USB_EP_STALL_bm) +#define udd_control_out_is_stalled() (udd_sram.ep_ctrl[0].STATUS&USB_EP_STALLF_bm ? true : false) +#define udd_control_out_ack_stall() LACR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_STALLF_bm) +#define udd_control_out_set_NACK0() LASR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_BUSNACK0_bm) +#define udd_control_out_clear_NACK0() LACR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_BUSNACK0_bm) + +#define udd_control_out_overflow() (udd_sram.ep_ctrl[0].STATUS&USB_EP_OVF_bm ? true : false) +#define udd_control_ack_out_overflow() LACR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_OVF_bm) + +#define udd_control_out_tc() (udd_sram.ep_ctrl[0].STATUS&USB_EP_TRNCOMPL0_bm ? true : false) +#define udd_control_out_ack_tc() LACR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_TRNCOMPL0_bm) +#define udd_control_out_set_tc() LASR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_TRNCOMPL0_bm) + +#define udd_control_out_dt_get() (udd_sram.ep_ctrl[0].STATUS&USB_EP_TOGGLE_bm ? true : false) +#define udd_control_out_dt_set() LASR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_TOGGLE_bm ) +#define udd_control_out_dt_clear() LACR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_TOGGLE_bm ) +#define udd_control_out_dt_toggle() LATR16(&udd_sram.ep_ctrl[0].STATUS,USB_EP_TOGGLE_bm) + +#define udd_control_out_set_buf(buf) (udd_sram.ep_ctrl[0].DATAPTR = (uint16_t) buf) + +#define udd_control_out_get_bytecnt() (udd_sram.ep_ctrl[0].CNT) +//! @} + +//! @name USB Device endpoint control IN field management +//! @{ +#define udd_control_in_is_enable_stall() (udd_sram.ep_ctrl[1].CTRL&USB_EP_STALL_bm ? true : false) +#define udd_control_in_enable_stall() LASR16(&udd_sram.ep_ctrl[1].CTRL,USB_EP_STALL_bm) +#define udd_control_in_disable_stall() LACR16(&udd_sram.ep_ctrl[1].CTRL,USB_EP_STALL_bm) +#define udd_control_in_is_stalled() (udd_sram.ep_ctrl[1].STATUS&USB_EP_STALLF_bm ? true : false) +#define udd_control_in_ack_stall() LACR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_STALLF_bm) +#define udd_control_in_set_NACK0() LASR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_BUSNACK0_bm) +#define udd_control_in_clear_NACK0() LACR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_BUSNACK0_bm) + +#define udd_control_in_underflow() (udd_sram.ep_ctrl[1].STATUS&USB_EP_UNF_bm ? true : false) +#define udd_control_ack_in_underflow() LACR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_UNF_bm) + +#define udd_control_in_tc() (udd_sram.ep_ctrl[1].STATUS&USB_EP_TRNCOMPL0_bm ? true : false) +#define udd_control_in_ack_tc() LACR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_TRNCOMPL0_bm) +#define udd_control_in_set_tc() LASR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_TRNCOMPL0_bm) + +#define udd_control_in_dt_get() (udd_sram.ep_ctrl[1].STATUS&USB_EP_TOGGLE_bm ? true : false) +#define udd_control_in_dt_set() LASR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_TOGGLE_bm ) +#define udd_control_in_dt_clear() LACR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_TOGGLE_bm ) +#define udd_control_in_dt_toggle() LATR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_TOGGLE_bm) + +#define udd_control_in_set_buf(buf) (udd_sram.ep_ctrl[1].DATAPTR = (uint16_t) buf) + +#define udd_control_in_set_bytecnt(n) (udd_sram.ep_ctrl[1].CNT = n) +//! @} +//! @} + +//! @} + +#endif // _USB_DEVICE_H_ diff --git a/DSTAT-temp/src/asf/xmega/utils/assembler.h b/DSTAT-temp/src/asf/xmega/utils/assembler.h new file mode 100644 index 0000000..0841e90 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/assembler.h @@ -0,0 +1,156 @@ +/** + * \file + * + * \brief Assembler abstraction layer and utilities + * + * Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef ASSEMBLER_H_INCLUDED +#define ASSEMBLER_H_INCLUDED + +#if !defined(__ASSEMBLER__) && !defined(__IAR_SYSTEMS_ASM__) \ + && !defined(__DOXYGEN__) +# error This file may only be included from assembly files +#endif + +#if defined(__ASSEMBLER__) +# include "assembler/gas.h" +# include +#elif defined(__IAR_SYSTEMS_ASM__) +# include "assembler/iar.h" +# include +#endif + +/** + * \ingroup group_xmega_utils + * \defgroup assembler_group Assembler Support + * + * This group provides a good handful of macros intended to smooth out + * the differences between various assemblers, similar to what compiler.h does + * for compilers, except that assemblers tend to be much less standardized than + * compilers. + * + * @{ + */ + +//! \name Control Statements +//@{ +/** + * \def REPEAT(count) + * \brief Repeat the following statements \a count times + */ +/** + * \def END_REPEAT() + * \brief Mark the end of the statements to be repeated + */ +/** + * \def SET_LOC(offset) + * \brief Set the location counter to \a offset + */ +/** + * \def END_FILE() + * \brief Mark the end of the file + */ +//@} + +//! \name Data Objects +//@{ +/** + * \def FILL_BYTES(count) + * \brief Allocate space for \a count bytes + */ +//@} + +//! \name Symbol Definition +//@{ +/** + * \def L(name) + * \brief Turn \a name into a local symbol, if possible + */ +/** + * \def EXTERN_SYMBOL(name) + * \brief Declare \a name as an external symbol referenced by this file + */ +/** + * \def FUNCTION(name) + * \brief Define a file-local function called \a name + */ +/** + * \def PUBLIC_FUNCTION(name) + * \brief Define a globally visible function called \a name + */ +/** + * \def WEAK_FUNCTION(name) + * \brief Define a weak function called \a name + * + * Weak functions are only referenced if no strong definitions are found + */ +/** + * \def WEAK_FUNCTION_ALIAS(name, strong_name) + * \brief Define \a name as a weak alias for the function \a strong_name + * \sa WEAK_FUNCTION + */ +/** + * \def END_FUNC(name) + * \brief Mark the end of the function called \a name + */ +//@} + +//! \name Section Definition +//@{ +/** + * \def TEXT_SECTION(name) + * \brief Start a new section containing executable code + */ +/** + * \def RODATA_SECTION(name) + * \brief Start a new section containing read-only data + */ +/** + * \def DATA_SECTION(name) + * \brief Start a new section containing writeable initialized data + */ +/** + * \def BSS_SECTION(name) + * \brief Start a new section containing writeable zero-initialized data + */ +//@} + +//! @} + +#endif /* ASSEMBLER_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/xmega/utils/assembler/gas.h b/DSTAT-temp/src/asf/xmega/utils/assembler/gas.h new file mode 100644 index 0000000..23c946a --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/assembler/gas.h @@ -0,0 +1,121 @@ +/** + * \file + * + * \brief Assembler abstraction layer: GNU Assembler specifics + * + * Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef ASSEMBLER_GAS_H_INCLUDED +#define ASSEMBLER_GAS_H_INCLUDED + +#ifndef __DOXYGEN__ + + /* IAR doesn't accept dots in macro names */ + .macro ld_addr, reg, sym + lda.w \reg, \sym + .endm + + /* Define a function \a name that is either globally visible or only + * file-local. + */ + .macro gas_begin_func name, is_public + .if \is_public + .global \name + .endif + .section .text.\name, "ax", @progbits + .type \name, @function + \name : + .endm + + /* Define a function \a name that is either globally visible or only + * file-local in a given segment. + */ + .macro gas_begin_func_segm name, is_public, segment + .if \is_public + .global \name + .endif + .section .\segment, "ax", @progbits + .type \name, @function + \name : + .endm + + /* Define \a name as a weak alias for the function \a strong_name */ + .macro gas_weak_function_alias name, strong_name + .global \name + .weak \name + .type \name, @function + .set \name, \strong_name + .endm + + /* Define a weak function called \a name */ + .macro gas_weak_function name + .weak \name + gas_begin_func \name 1 + .endm + +#define REPEAT(count) .rept count +#define END_REPEAT() .endr +#define FILL_BYTES(count) .fill count +#define SET_LOC(offset) .org offset +#define L(name) .L##name +#define EXTERN_SYMBOL(name) + +#define TEXT_SECTION(name) \ + .section name, "ax", @progbits +#define RODATA_SECTION(name) \ + .section name, "a", @progbits +#define DATA_SECTION(name) \ + .section name, "aw", @progbits +#define BSS_SECTION(name) \ + .section name, "aw", @nobits + +#define FUNCTION(name) gas_begin_func name 0 +#define PUBLIC_FUNCTION(name) gas_begin_func name 1 +#define PUBLIC_FUNCTION_SEGMENT(name, segment) \ + gas_begin_func_segm name 1 segment +#define WEAK_FUNCTION(name) gas_weak_function name +#define WEAK_FUNCTION_ALIAS(name, strong_name) \ + gas_weak_function_alias name strong_name +#define END_FUNC(name) \ + .size name, . - name + +#define END_FILE() + +#endif /* __DOXYGEN__ */ + +#endif /* ASSEMBLER_GAS_H_INCLUDED */ diff --git a/DSTAT-temp/src/asf/xmega/utils/bit_handling/clz_ctz.h b/DSTAT-temp/src/asf/xmega/utils/bit_handling/clz_ctz.h new file mode 100644 index 0000000..682ad28 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/bit_handling/clz_ctz.h @@ -0,0 +1,212 @@ +/** + * \file + * + * \brief CLZ/CTZ C implementation. + * + * Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef CLZ_CTH_H +#define CLZ_CTH_H + +/** + * \brief Count leading zeros in unsigned integer + * + * This macro takes unsigned integers of any size, and evaluates to a call to + * the clz-function for its size. These functions count the number of zeros, + * starting with the MSB, before a one occurs in the integer. + * + * \param x Unsigned integer to count the leading zeros in. + * + * \return The number of leading zeros in \a x. + */ +#define clz(x) compiler_demux_size(sizeof(x), clz, (x)) + +/** + * \internal + * \brief Count leading zeros in unsigned, 8-bit integer + * + * \param x Unsigned byte to count the leading zeros in. + * + * \return The number of leading zeros in \a x. + */ +__always_inline static uint8_t clz8(uint8_t x) +{ + uint8_t bit = 0; + + if (x & 0xf0) { + x >>= 4; + } else { + bit += 4; + } + + if (x & 0x0c) { + x >>= 2; + } else { + bit += 2; + } + + if (!(x & 0x02)) { + bit++; + } + + return bit; + +} + +/** + * \internal + * \brief Count leading zeros in unsigned, 16-bit integer + * + * \param x Unsigned word to count the leading zeros in. + * + * \return The number of leading zeros in \a x. + */ +__always_inline static uint8_t clz16(uint16_t x) +{ + uint8_t bit = 0; + + if (x & 0xff00) { + x >>= 8; + } else { + bit += 8; + } + + return bit + clz8(x); +} + +/** + * \internal + * \brief Count leading zeros in unsigned, 32-bit integer + * + * \param x Unsigned double word to count the leading zeros in. + * + * \return The number of leading zeros in \a x. + */ +__always_inline static uint8_t clz32(uint32_t x) +{ + uint8_t bit = 0; + + if (x & 0xffff0000) { + x >>= 16; + } else { + bit += 16; + } + + return bit + clz16(x); +} + +/** + * \brief Count trailing zeros in unsigned integer + * + * This macro takes unsigned integers of any size, and evaluates to a call to + * the ctz-function for its size. These functions count the number of zeros, + * starting with the LSB, before a one occurs in the integer. + * + * \param x Unsigned integer to count the trailing zeros in. + * + * \return The number of trailing zeros in \a x. + */ +#define ctz(x) compiler_demux_size(sizeof(x), ctz, (x)) + +/** + * \internal + * \brief Count trailing zeros in unsigned, 8-bit integer + * + * \param x Unsigned byte to count the trailing zeros in. + * + * \return The number of leading zeros in \a x. + */ +__always_inline static uint8_t ctz8(uint8_t x) +{ + uint8_t bit = 0; + + if (!(x & 0x0f)) { + bit += 4; + x >>= 4; + } + if (!(x & 0x03)) { + bit += 2; + x >>= 2; + } + if (!(x & 0x01)) + bit++; + + return bit; +} + +/** + * \internal + * \brief Count trailing zeros in unsigned, 16-bit integer + * + * \param x Unsigned word to count the trailing zeros in. + * + * \return The number of trailing zeros in \a x. + */ +__always_inline static uint8_t ctz16(uint16_t x) +{ + uint8_t bit = 0; + + if (!(x & 0x00ff)) { + bit += 8; + x >>= 8; + } + + return bit + ctz8(x); +} + +/** + * \internal + * \brief Count trailing zeros in unsigned, 32-bit integer + * + * \param x Unsigned double word to count the trailing zeros in. + * + * \return The number of trailing zeros in \a x. + */ +__always_inline static uint8_t ctz32(uint32_t x) +{ + uint8_t bit = 0; + + if (!(x & 0x0000ffff)) { + bit += 16; + x >>= 16; + } + + return bit + ctz16(x); +} + +#endif /* CLZ_CTZ_H */ diff --git a/DSTAT-temp/src/asf/xmega/utils/compiler.h b/DSTAT-temp/src/asf/xmega/utils/compiler.h new file mode 100644 index 0000000..7a86adb --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/compiler.h @@ -0,0 +1,1039 @@ +/** + * \file + * + * \brief Commonly used includes, types and macros. + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef UTILS_COMPILER_H +#define UTILS_COMPILER_H + +/** + * \defgroup group_xmega_utils XMEGA compiler driver + * + * Compiler abstraction layer and code utilities for 8-bit AVR. + * This module provides various abstraction layers and utilities to make code compatible between different compilers. + * + * \{ + */ + +#if defined(__GNUC__) +# include +# include +#elif defined(__ICCAVR__) +# include +# include +#else +# error Unsupported compiler. +#endif + +#include +#include +#include +#include + +#include + +#ifdef __ICCAVR__ +/*! \name Compiler Keywords + * + * Port of some keywords from GCC to IAR Embedded Workbench. + */ +//! @{ +#define __asm__ asm +#define __inline__ inline +#define __volatile__ +//! @} +#endif + +/** + * \def UNUSED + * \brief Marking \a v as a unused parameter or value. + */ +#define UNUSED(v) (void)(v) + +/** + * \def unused + * \brief Marking \a v as a unused parameter or value. + */ +#define unused(v) do { (void)(v); } while(0) + +/** + * \def barrier + * \brief Memory barrier + */ +#ifdef __GNUC__ +# define barrier() asm volatile("" ::: "memory") +#else +# define barrier() asm ("") +#endif + +/** + * \brief Emit the compiler pragma \a arg. + * + * \param arg The pragma directive as it would appear after \e \#pragma + * (i.e. not stringified). + */ +#define COMPILER_PRAGMA(arg) _Pragma(#arg) + +/* + * AVR arch does not care about alignment anyway. + */ +#define COMPILER_PACK_RESET(alignment) +#define COMPILER_PACK_SET(alignment) + +/** + * \brief Set aligned boundary. + */ +#if (defined __GNUC__) +#define COMPILER_ALIGNED(a) __attribute__((__aligned__(a))) +#elif (defined __ICCAVR__) +#define COMPILER_ALIGNED(a) COMPILER_PRAGMA(data_alignment = a) +#endif + +/** + * \brief Set word-aligned boundary. + */ +#if (defined __GNUC__) +#define COMPILER_WORD_ALIGNED __attribute__((__aligned__(2))) +#elif (defined __ICCAVR__) +#define COMPILER_WORD_ALIGNED COMPILER_PRAGMA(data_alignment = 2) +#endif + +/** + * \name Tag functions as deprecated + * + * Tagging a function as deprecated will produce a warning when and only + * when the function is called. + * + * Usage is to add the __DEPRECATED__ symbol before the function definition. + * E.g.: + * __DEPRECATED__ uint8_t some_deprecated_function (void) + * { + * ... + * } + * + * \note Only supported by GCC 3.1 and above, no IAR support + * @{ + */ +#if ((defined __GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >=1))) +#define __DEPRECATED__ __attribute__((__deprecated__)) +#else +#define __DEPRECATED__ +#endif +//! @} + +/*! \name Usual Types + */ +//! @{ +typedef unsigned char Bool; //!< Boolean. +#ifndef __cplusplus +#if !defined(__bool_true_false_are_defined) +typedef unsigned char bool; //!< Boolean. +#endif +#endif +typedef signed char S8 ; //!< 8-bit signed integer. +typedef unsigned char U8 ; //!< 8-bit unsigned integer. +typedef signed short int S16; //!< 16-bit signed integer. +typedef unsigned short int U16; //!< 16-bit unsigned integer. +typedef unsigned short int le16_t; +typedef unsigned short int be16_t; +typedef signed long int S32; //!< 32-bit signed integer. +typedef unsigned long int U32; //!< 32-bit unsigned integer. +typedef uint32_t le32_t; +typedef uint32_t be32_t; +typedef signed long long int S64; //!< 64-bit signed integer. +typedef unsigned long long int U64; //!< 64-bit unsigned integer. +typedef float F32; //!< 32-bit floating-point number. +typedef double F64; //!< 64-bit floating-point number. +typedef uint16_t iram_size_t; +//! @} + + +/*! \name Status Types + */ +//! @{ +typedef Bool Status_bool_t; //!< Boolean status. +typedef U8 Status_t; //!< 8-bit-coded status. +//! @} + + +/*! \name Aliasing Aggregate Types + */ +//! @{ + +//! 16-bit union. +typedef union +{ + S16 s16 ; + U16 u16 ; + S8 s8 [2]; + U8 u8 [2]; +} Union16; + +//! 32-bit union. +typedef union +{ + S32 s32 ; + U32 u32 ; + S16 s16[2]; + U16 u16[2]; + S8 s8 [4]; + U8 u8 [4]; +} Union32; + +//! 64-bit union. +typedef union +{ + S64 s64 ; + U64 u64 ; + S32 s32[2]; + U32 u32[2]; + S16 s16[4]; + U16 u16[4]; + S8 s8 [8]; + U8 u8 [8]; +} Union64; + +//! Union of pointers to 64-, 32-, 16- and 8-bit unsigned integers. +typedef union +{ + S64 *s64ptr; + U64 *u64ptr; + S32 *s32ptr; + U32 *u32ptr; + S16 *s16ptr; + U16 *u16ptr; + S8 *s8ptr ; + U8 *u8ptr ; +} UnionPtr; + +//! Union of pointers to volatile 64-, 32-, 16- and 8-bit unsigned integers. +typedef union +{ + volatile S64 *s64ptr; + volatile U64 *u64ptr; + volatile S32 *s32ptr; + volatile U32 *u32ptr; + volatile S16 *s16ptr; + volatile U16 *u16ptr; + volatile S8 *s8ptr ; + volatile U8 *u8ptr ; +} UnionVPtr; + +//! Union of pointers to constant 64-, 32-, 16- and 8-bit unsigned integers. +typedef union +{ + const S64 *s64ptr; + const U64 *u64ptr; + const S32 *s32ptr; + const U32 *u32ptr; + const S16 *s16ptr; + const U16 *u16ptr; + const S8 *s8ptr ; + const U8 *u8ptr ; +} UnionCPtr; + +//! Union of pointers to constant volatile 64-, 32-, 16- and 8-bit unsigned integers. +typedef union +{ + const volatile S64 *s64ptr; + const volatile U64 *u64ptr; + const volatile S32 *s32ptr; + const volatile U32 *u32ptr; + const volatile S16 *s16ptr; + const volatile U16 *u16ptr; + const volatile S8 *s8ptr ; + const volatile U8 *u8ptr ; +} UnionCVPtr; + +//! Structure of pointers to 64-, 32-, 16- and 8-bit unsigned integers. +typedef struct +{ + S64 *s64ptr; + U64 *u64ptr; + S32 *s32ptr; + U32 *u32ptr; + S16 *s16ptr; + U16 *u16ptr; + S8 *s8ptr ; + U8 *u8ptr ; +} StructPtr; + +//! Structure of pointers to volatile 64-, 32-, 16- and 8-bit unsigned integers. +typedef struct +{ + volatile S64 *s64ptr; + volatile U64 *u64ptr; + volatile S32 *s32ptr; + volatile U32 *u32ptr; + volatile S16 *s16ptr; + volatile U16 *u16ptr; + volatile S8 *s8ptr ; + volatile U8 *u8ptr ; +} StructVPtr; + +//! Structure of pointers to constant 64-, 32-, 16- and 8-bit unsigned integers. +typedef struct +{ + const S64 *s64ptr; + const U64 *u64ptr; + const S32 *s32ptr; + const U32 *u32ptr; + const S16 *s16ptr; + const U16 *u16ptr; + const S8 *s8ptr ; + const U8 *u8ptr ; +} StructCPtr; + +//! Structure of pointers to constant volatile 64-, 32-, 16- and 8-bit unsigned integers. +typedef struct +{ + const volatile S64 *s64ptr; + const volatile U64 *u64ptr; + const volatile S32 *s32ptr; + const volatile U32 *u32ptr; + const volatile S16 *s16ptr; + const volatile U16 *u16ptr; + const volatile S8 *s8ptr ; + const volatile U8 *u8ptr ; +} StructCVPtr; + +//! @} + + +//_____ M A C R O S ________________________________________________________ + +/*! \name Usual Constants + */ +//! @{ +#define DISABLE 0 +#define ENABLE 1 +#ifndef __cplusplus +#if !defined(__bool_true_false_are_defined) +#define false 0 +#define true 1 +#endif +#endif +#define PASS 0 +#define FAIL 1 +#define LOW 0 +#define HIGH 1 +//! @} + + +//! \name Compile time error handling +//@{ + +/** + * \internal + * \def ERROR_FUNC(name, msg) + * \brief Fail compilation if function call isn't eliminated + * + * If the compiler fails to optimize away all calls to the function \a + * name, terminate compilation and display \a msg to the user. + * + * \note Not all compilers support this, so this is best-effort only. + * Sometimes, there may be a linker error instead, and when optimization + * is disabled, this mechanism will be completely disabled. + */ +#ifndef ERROR_FUNC +# define ERROR_FUNC(name, msg) \ + extern int name(void) +#endif + +//@} + +//! \name Function call demultiplexing +//@{ + +//! Error function for failed demultiplexing. +ERROR_FUNC(compiler_demux_bad_size, "Invalid parameter size"); + +/** + * \internal + * \brief Demultiplex function call based on size of datatype + * + * Evaluates to a function call to a function name with suffix 8, 16 or 32 + * depending on the size of the datatype. Any number of parameters can be + * passed to the function. + * + * Usage: + * \code + * void foo8(uint8_t a, void *b); + * void foo16(uint16_t a, void *b); + * void foo32(uint32_t a, void *b); + * + * #define foo(x, y) compiler_demux_size(sizeof(x), foo, x, y) + * \endcode + * + * \param size Size of the datatype. + * \param func Base function name. + * \param ... List of parameters to pass to the function. + */ +#define compiler_demux_size(size, func, ...) \ + (((size) == 1) ? func##8(__VA_ARGS__) : \ + ((size) == 2) ? func##16(__VA_ARGS__) : \ + ((size) == 4) ? func##32(__VA_ARGS__) : \ + compiler_demux_bad_size()) + +//@} + +/** + * \def __always_inline + * \brief The function should always be inlined. + * + * This annotation instructs the compiler to ignore its inlining + * heuristics and inline the function no matter how big it thinks it + * becomes. + */ +#if (defined __GNUC__) + #define __always_inline inline __attribute__((__always_inline__)) +#elif (defined __ICCAVR__) + #define __always_inline _Pragma("inline=forced") +#endif + +//! \name Optimization Control +//@{ + +/** + * \def __always_optimize + * \brief The function should always be optimized. + * + * This annotation instructs the compiler to ignore global optimization + * settings and always compile the function with a high level of + * optimization. + */ +#if (defined __GNUC__) + #define __always_optimize __attribute__((optimize(3))) +#elif (defined __ICCAVR__) + #define __always_optimize _Pragma("optimize=high") +#endif + +/** + * \def likely(exp) + * \brief The expression \a exp is likely to be true + */ +#ifndef likely +# define likely(exp) (exp) +#endif + +/** + * \def unlikely(exp) + * \brief The expression \a exp is unlikely to be true + */ +#ifndef unlikely +# define unlikely(exp) (exp) +#endif + +/** + * \def is_constant(exp) + * \brief Determine if an expression evaluates to a constant value. + * + * \param exp Any expression + * + * \return true if \a exp is constant, false otherwise. + */ +#ifdef __GNUC__ +# define is_constant(exp) __builtin_constant_p(exp) +#else +# define is_constant(exp) (0) +#endif + +//! @} + +/*! \name Bit-Field Handling + */ +#include "bit_handling/clz_ctz.h" +//! @{ + +/*! \brief Reads the bits of a value specified by a given bit-mask. + * + * \param value Value to read bits from. + * \param mask Bit-mask indicating bits to read. + * + * \return Read bits. + */ +#define Rd_bits( value, mask) ((value)&(mask)) + +/*! \brief Writes the bits of a C lvalue specified by a given bit-mask. + * + * \param lvalue C lvalue to write bits to. + * \param mask Bit-mask indicating bits to write. + * \param bits Bits to write. + * + * \return Resulting value with written bits. + */ +#define Wr_bits(lvalue, mask, bits) ((lvalue) = ((lvalue) & ~(mask)) |\ + ((bits ) & (mask))) + +/*! \brief Tests the bits of a value specified by a given bit-mask. + * + * \param value Value of which to test bits. + * \param mask Bit-mask indicating bits to test. + * + * \return \c 1 if at least one of the tested bits is set, else \c 0. + */ +#define Tst_bits( value, mask) (Rd_bits(value, mask) != 0) + +/*! \brief Clears the bits of a C lvalue specified by a given bit-mask. + * + * \param lvalue C lvalue of which to clear bits. + * \param mask Bit-mask indicating bits to clear. + * + * \return Resulting value with cleared bits. + */ +#define Clr_bits(lvalue, mask) ((lvalue) &= ~(mask)) + +/*! \brief Sets the bits of a C lvalue specified by a given bit-mask. + * + * \param lvalue C lvalue of which to set bits. + * \param mask Bit-mask indicating bits to set. + * + * \return Resulting value with set bits. + */ +#define Set_bits(lvalue, mask) ((lvalue) |= (mask)) + +/*! \brief Toggles the bits of a C lvalue specified by a given bit-mask. + * + * \param lvalue C lvalue of which to toggle bits. + * \param mask Bit-mask indicating bits to toggle. + * + * \return Resulting value with toggled bits. + */ +#define Tgl_bits(lvalue, mask) ((lvalue) ^= (mask)) + +/*! \brief Reads the bit-field of a value specified by a given bit-mask. + * + * \param value Value to read a bit-field from. + * \param mask Bit-mask indicating the bit-field to read. + * + * \return Read bit-field. + */ +#define Rd_bitfield( value,mask) (Rd_bits( value, (uint32_t)mask) >> ctz(mask)) + +/*! \brief Writes the bit-field of a C lvalue specified by a given bit-mask. + * + * \param lvalue C lvalue to write a bit-field to. + * \param mask Bit-mask indicating the bit-field to write. + * \param bitfield Bit-field to write. + * + * \return Resulting value with written bit-field. + */ +#define Wr_bitfield(lvalue, mask, bitfield) (Wr_bits(lvalue, mask, (uint32_t)(bitfield) << ctz(mask))) + +//! @} + + +/*! \brief This macro is used to test fatal errors. + * + * The macro tests if the expression is false. If it is, a fatal error is + * detected and the application hangs up. If TEST_SUITE_DEFINE_ASSERT_MACRO + * is defined, a unit test version of the macro is used, to allow execution + * of further tests after a false expression. + * + * \param expr Expression to evaluate and supposed to be nonzero. + */ +#if defined(_ASSERT_ENABLE_) +# if defined(TEST_SUITE_DEFINE_ASSERT_MACRO) + // Assert() is defined in unit_test/suite.h +# include "unit_test/suite.h" +# else +# define Assert(expr) \ + {\ + if (!(expr)) while (true);\ + } +# endif +#else +# define Assert(expr) ((void) 0) +#endif + +/*! \name Bit Reversing + */ +//! @{ + +/*! \brief Reverses the bits of \a u8. + * + * \param u8 U8 of which to reverse the bits. + * + * \return Value resulting from \a u8 with reversed bits. + */ +#define bit_reverse8(u8) ((U8)(bit_reverse32((U8)(u8)) >> 24)) + +/*! \brief Reverses the bits of \a u16. + * + * \param u16 U16 of which to reverse the bits. + * + * \return Value resulting from \a u16 with reversed bits. + */ +#define bit_reverse16(u16) ((U16)(bit_reverse32((U16)(u16)) >> 16)) + +/*! \brief Reverses the bits of \a u32. + * + * \param u32 U32 of which to reverse the bits. + * + * \return Value resulting from \a u32 with reversed bits. + */ +#if (defined __GNUC__) + #define bit_reverse32(u32) \ + (\ + {\ + unsigned int __value = (U32)(u32);\ + __asm__ ("brev\t%0" : "+r" (__value) : : "cc");\ + (U32)__value;\ + }\ + ) +#elif (defined __ICCAVR__) + #define bit_reverse32(u32) ((U32)__bit_reverse((U32)(u32))) +#endif + +/*! \brief Reverses the bits of \a u64. + * + * \param u64 U64 of which to reverse the bits. + * + * \return Value resulting from \a u64 with reversed bits. + */ +#define bit_reverse64(u64) ((U64)(((U64)bit_reverse32((U64)(u64) >> 32)) |\ + ((U64)bit_reverse32((U64)(u64)) << 32))) + +//! @} + +//! \name Logarithmic functions +//! @{ + +/** + * \internal + * Undefined function. Will cause a link failure if ilog2() is called + * with an invalid constant value. + */ +int_fast8_t ilog2_undefined(void); + +/** + * \brief Calculate the base-2 logarithm of a number rounded down to + * the nearest integer. + * + * \param x A 32-bit value + * \return The base-2 logarithm of \a x, or -1 if \a x is 0. + */ +static inline int_fast8_t ilog2(uint32_t x) +{ + if (is_constant(x)) + return ((x) & (1ULL << 31) ? 31 : + (x) & (1ULL << 30) ? 30 : + (x) & (1ULL << 29) ? 29 : + (x) & (1ULL << 28) ? 28 : + (x) & (1ULL << 27) ? 27 : + (x) & (1ULL << 26) ? 26 : + (x) & (1ULL << 25) ? 25 : + (x) & (1ULL << 24) ? 24 : + (x) & (1ULL << 23) ? 23 : + (x) & (1ULL << 22) ? 22 : + (x) & (1ULL << 21) ? 21 : + (x) & (1ULL << 20) ? 20 : + (x) & (1ULL << 19) ? 19 : + (x) & (1ULL << 18) ? 18 : + (x) & (1ULL << 17) ? 17 : + (x) & (1ULL << 16) ? 16 : + (x) & (1ULL << 15) ? 15 : + (x) & (1ULL << 14) ? 14 : + (x) & (1ULL << 13) ? 13 : + (x) & (1ULL << 12) ? 12 : + (x) & (1ULL << 11) ? 11 : + (x) & (1ULL << 10) ? 10 : + (x) & (1ULL << 9) ? 9 : + (x) & (1ULL << 8) ? 8 : + (x) & (1ULL << 7) ? 7 : + (x) & (1ULL << 6) ? 6 : + (x) & (1ULL << 5) ? 5 : + (x) & (1ULL << 4) ? 4 : + (x) & (1ULL << 3) ? 3 : + (x) & (1ULL << 2) ? 2 : + (x) & (1ULL << 1) ? 1 : + (x) & (1ULL << 0) ? 0 : + ilog2_undefined()); + + return 31 - clz(x); +} + +//! @} + +/*! \name Alignment + */ +//! @{ + +/*! \brief Tests alignment of the number \a val with the \a n boundary. + * + * \param val Input value. + * \param n Boundary. + * + * \return \c 1 if the number \a val is aligned with the \a n boundary, else \c 0. + */ +#define Test_align(val, n ) (!Tst_bits( val, (n) - 1 ) ) + +/*! \brief Gets alignment of the number \a val with respect to the \a n boundary. + * + * \param val Input value. + * \param n Boundary. + * + * \return Alignment of the number \a val with respect to the \a n boundary. + */ +#define Get_align( val, n ) ( Rd_bits( val, (n) - 1 ) ) + +/*! \brief Sets alignment of the lvalue number \a lval to \a alg with respect to the \a n boundary. + * + * \param lval Input/output lvalue. + * \param n Boundary. + * \param alg Alignment. + * + * \return New value of \a lval resulting from its alignment set to \a alg with respect to the \a n boundary. + */ +#define Set_align(lval, n, alg) ( Wr_bits(lval, (n) - 1, alg) ) + +/*! \brief Aligns the number \a val with the upper \a n boundary. + * + * \param val Input value. + * \param n Boundary. + * + * \return Value resulting from the number \a val aligned with the upper \a n boundary. + */ +#define Align_up( val, n ) (((val) + ((n) - 1)) & ~((n) - 1)) + +/*! \brief Aligns the number \a val with the lower \a n boundary. + * + * \param val Input value. + * \param n Boundary. + * + * \return Value resulting from the number \a val aligned with the lower \a n boundary. + */ +#define Align_down(val, n ) ( (val) & ~((n) - 1)) + +//! @} + + +/*! \name Mathematics + * + * Compiler optimization for non-constant expressions, only for abs under WinAVR + */ +//! @{ + +/*! \brief Takes the absolute value of \a a. + * + * \param a Input value. + * + * \return Absolute value of \a a. + * + * \note More optimized if only used with values known at compile time. + */ +#define Abs(a) (((a) < 0 ) ? -(a) : (a)) +#ifndef abs +#define abs(a) Abs(a) +#endif + +/*! \brief Takes the minimal value of \a a and \a b. + * + * \param a Input value. + * \param b Input value. + * + * \return Minimal value of \a a and \a b. + * + * \note More optimized if only used with values known at compile time. + */ +#define Min(a, b) (((a) < (b)) ? (a) : (b)) +#define min(a, b) Min(a, b) + +/*! \brief Takes the maximal value of \a a and \a b. + * + * \param a Input value. + * \param b Input value. + * + * \return Maximal value of \a a and \a b. + * + * \note More optimized if only used with values known at compile time. + */ +#define Max(a, b) (((a) > (b)) ? (a) : (b)) +#define max(a, b) Max(a, b) + +//! @} + + +/*! \brief Calls the routine at address \a addr. + * + * It generates a long call opcode. + * + * For example, `Long_call(0x80000000)' generates a software reset on a UC3 if + * it is invoked from the CPU supervisor mode. + * + * \param addr Address of the routine to call. + * + * \note It may be used as a long jump opcode in some special cases. + */ +#define Long_call(addr) ((*(void (*)(void))(addr))()) + +/*! \name System Register Access + */ +//! @{ + +/*! \brief Gets the value of the \a sysreg system register. + * + * \param sysreg Address of the system register of which to get the value. + * + * \return Value of the \a sysreg system register. + */ +#if (defined __GNUC__) + #define Get_system_register(sysreg) __builtin_mfsr(sysreg) +#elif (defined __ICCAVR__) + #define Get_system_register(sysreg) __get_system_register(sysreg) +#endif + +/*! \brief Sets the value of the \a sysreg system register to \a value. + * + * \param sysreg Address of the system register of which to set the value. + * \param value Value to set the \a sysreg system register to. + */ +#if (defined __GNUC__) + #define Set_system_register(sysreg, value) __builtin_mtsr(sysreg, value) +#elif (defined __ICCAVR__) + #define Set_system_register(sysreg, value) __set_system_register(sysreg, value) +#endif + +//! @} + +/*! \name Debug Register Access + */ +//! @{ + +/*! \brief Gets the value of the \a dbgreg debug register. + * + * \param dbgreg Address of the debug register of which to get the value. + * + * \return Value of the \a dbgreg debug register. + */ +#if (defined __GNUC__) + #define Get_debug_register(dbgreg) __builtin_mfdr(dbgreg) +#elif (defined __ICCAVR__) + #define Get_debug_register(dbgreg) __get_debug_register(dbgreg) +#endif + +/*! \brief Sets the value of the \a dbgreg debug register to \a value. + * + * \param dbgreg Address of the debug register of which to set the value. + * \param value Value to set the \a dbgreg debug register to. + */ +#if (defined __GNUC__) + #define Set_debug_register(dbgreg, value) __builtin_mtdr(dbgreg, value) +#elif (defined __ICCAVR__) + #define Set_debug_register(dbgreg, value) __set_debug_register(dbgreg, value) +#endif + +//! @} + + +/*! \name MCU Endianism Handling + * xmega is a MCU little endianism. + */ +//! @{ +#define MSB(u16) (((uint8_t* )&u16)[1]) +#define LSB(u16) (((uint8_t* )&u16)[0]) + +#define MSW(u32) (((uint16_t*)&u32)[1]) +#define LSW(u32) (((uint16_t*)&u32)[0]) +#define MSB0W(u32) (((uint8_t*)&(u32))[3]) //!< Most significant byte of 1st rank of \a u32. +#define MSB1W(u32) (((uint8_t*)&(u32))[2]) //!< Most significant byte of 2nd rank of \a u32. +#define MSB2W(u32) (((uint8_t*)&(u32))[1]) //!< Most significant byte of 3rd rank of \a u32. +#define MSB3W(u32) (((uint8_t*)&(u32))[0]) //!< Most significant byte of 4th rank of \a u32. +#define LSB3W(u32) MSB0W(u32) //!< Least significant byte of 4th rank of \a u32. +#define LSB2W(u32) MSB1W(u32) //!< Least significant byte of 3rd rank of \a u32. +#define LSB1W(u32) MSB2W(u32) //!< Least significant byte of 2nd rank of \a u32. +#define LSB0W(u32) MSB3W(u32) //!< Least significant byte of 1st rank of \a u32. + +#define MSB0(u32) (((uint8_t*)&u32)[3]) +#define MSB1(u32) (((uint8_t*)&u32)[2]) +#define MSB2(u32) (((uint8_t*)&u32)[1]) +#define MSB3(u32) (((uint8_t*)&u32)[0]) +#define LSB0(u32) MSB3(u32) +#define LSB1(u32) MSB2(u32) +#define LSB2(u32) MSB1(u32) +#define LSB3(u32) MSB0(u32) + +#define LE16(x) (x) +#define le16_to_cpu(x) (x) +#define cpu_to_le16(x) (x) +#define LE16_TO_CPU(x) (x) +#define CPU_TO_LE16(x) (x) + +#define BE16(x) Swap16(x) +#define be16_to_cpu(x) swap16(x) +#define cpu_to_be16(x) swap16(x) +#define BE16_TO_CPU(x) Swap16(x) +#define CPU_TO_BE16(x) Swap16(x) + +#define LE32(x) (x) +#define le32_to_cpu(x) (x) +#define cpu_to_le32(x) (x) +#define LE32_TO_CPU(x) (x) +#define CPU_TO_LE32(x) (x) + +#define BE32(x) Swap32(x) +#define be32_to_cpu(x) swap32(x) +#define cpu_to_be32(x) swap32(x) +#define BE32_TO_CPU(x) Swap32(x) +#define CPU_TO_BE32(x) Swap32(x) + + + +//! @} + + +/*! \name Endianism Conversion + * + * The same considerations as for clz and ctz apply here but AVR32-GCC's + * __builtin_bswap_16 and __builtin_bswap_32 do not behave like macros when + * applied to constant expressions, so two sets of macros are defined here: + * - Swap16, Swap32 and Swap64 to apply to constant expressions (values known + * at compile time); + * - swap16, swap32 and swap64 to apply to non-constant expressions (values + * unknown at compile time). + */ +//! @{ + +/*! \brief Toggles the endianism of \a u16 (by swapping its bytes). + * + * \param u16 U16 of which to toggle the endianism. + * + * \return Value resulting from \a u16 with toggled endianism. + * + * \note More optimized if only used with values known at compile time. + */ +#define Swap16(u16) ((U16)(((U16)(u16) >> 8) |\ + ((U16)(u16) << 8))) + +/*! \brief Toggles the endianism of \a u32 (by swapping its bytes). + * + * \param u32 U32 of which to toggle the endianism. + * + * \return Value resulting from \a u32 with toggled endianism. + * + * \note More optimized if only used with values known at compile time. + */ +#define Swap32(u32) ((U32)(((U32)Swap16((U32)(u32) >> 16)) |\ + ((U32)Swap16((U32)(u32)) << 16))) + +/*! \brief Toggles the endianism of \a u64 (by swapping its bytes). + * + * \param u64 U64 of which to toggle the endianism. + * + * \return Value resulting from \a u64 with toggled endianism. + * + * \note More optimized if only used with values known at compile time. + */ +#define Swap64(u64) ((U64)(((U64)Swap32((U64)(u64) >> 32)) |\ + ((U64)Swap32((U64)(u64)) << 32))) + +/*! \brief Toggles the endianism of \a u16 (by swapping its bytes). + * + * \param u16 U16 of which to toggle the endianism. + * + * \return Value resulting from \a u16 with toggled endianism. + * + * \note More optimized if only used with values unknown at compile time. + */ +#define swap16(u16) Swap16(u16) + +/*! \brief Toggles the endianism of \a u32 (by swapping its bytes). + * + * \param u32 U32 of which to toggle the endianism. + * + * \return Value resulting from \a u32 with toggled endianism. + * + * \note More optimized if only used with values unknown at compile time. + */ +#define swap32(u32) Swap32(u32) + +/*! \brief Toggles the endianism of \a u64 (by swapping its bytes). + * + * \param u64 U64 of which to toggle the endianism. + * + * \return Value resulting from \a u64 with toggled endianism. + * + * \note More optimized if only used with values unknown at compile time. + */ +#define swap64(u64) ((U64)(((U64)swap32((U64)(u64) >> 32)) |\ + ((U64)swap32((U64)(u64)) << 32))) + +//! @} + + +/*! \name Target Abstraction + */ +//! @{ + +#define _GLOBEXT_ extern //!< extern storage-class specifier. +#define _CONST_TYPE_ const //!< const type qualifier. +#define _MEM_TYPE_SLOW_ //!< Slow memory type. +#define _MEM_TYPE_MEDFAST_ //!< Fairly fast memory type. +#define _MEM_TYPE_FAST_ //!< Fast memory type. + +typedef U8 Byte; //!< 8-bit unsigned integer. + +#define memcmp_ram2ram memcmp //!< Target-specific memcmp of RAM to RAM. +#define memcmp_code2ram memcmp //!< Target-specific memcmp of RAM to NVRAM. +#define memcpy_ram2ram memcpy //!< Target-specific memcpy from RAM to RAM. +#define memcpy_code2ram memcpy //!< Target-specific memcpy from NVRAM to RAM. + +//! @} + +/** + * \brief Calculate \f$ \left\lceil \frac{a}{b} \right\rceil \f$ using + * integer arithmetic. + * + * \param a An integer + * \param b Another integer + * + * \return (\a a / \a b) rounded up to the nearest integer. + */ +#define div_ceil(a, b) (((a) + (b) - 1) / (b)) + +#include "preprocessor.h" +#include "progmem.h" +#include "interrupt.h" + +/** + * \} + */ + +#endif // UTILS_COMPILER_H diff --git a/DSTAT-temp/src/asf/xmega/utils/preprocessor/mrepeat.h b/DSTAT-temp/src/asf/xmega/utils/preprocessor/mrepeat.h new file mode 100644 index 0000000..547dd1c --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/preprocessor/mrepeat.h @@ -0,0 +1,335 @@ +/** + * \file + * + * \brief Preprocessor macro repeating utils. + * + * Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef _MREPEAT_H_ +#define _MREPEAT_H_ + +/** + * \defgroup group_xmega_utils_mrepeat Macro Repeat + * + * \ingroup group_xmega_utils + * + * \{ + */ + +#include "preprocessor.h" + + +//! Maximal number of repetitions supported by MREPEAT. +#define MREPEAT_LIMIT 256 + +/*! \brief Macro repeat. + * + * This macro represents a horizontal repetition construct. + * + * \param count The number of repetitious calls to macro. Valid values range from 0 to MREPEAT_LIMIT. + * \param macro A binary operation of the form macro(n, data). This macro is expanded by MREPEAT with + * the current repetition number and the auxiliary data argument. + * \param data Auxiliary data passed to macro. + * + * \return macro(0, data) macro(1, data) ... macro(count - 1, data) + */ +#define MREPEAT(count, macro, data) TPASTE2(MREPEAT, count)(macro, data) + +#define MREPEAT0( macro, data) +#define MREPEAT1( macro, data) MREPEAT0( macro, data) macro( 0, data) +#define MREPEAT2( macro, data) MREPEAT1( macro, data) macro( 1, data) +#define MREPEAT3( macro, data) MREPEAT2( macro, data) macro( 2, data) +#define MREPEAT4( macro, data) MREPEAT3( macro, data) macro( 3, data) +#define MREPEAT5( macro, data) MREPEAT4( macro, data) macro( 4, data) +#define MREPEAT6( macro, data) MREPEAT5( macro, data) macro( 5, data) +#define MREPEAT7( macro, data) MREPEAT6( macro, data) macro( 6, data) +#define MREPEAT8( macro, data) MREPEAT7( macro, data) macro( 7, data) +#define MREPEAT9( macro, data) MREPEAT8( macro, data) macro( 8, data) +#define MREPEAT10( macro, data) MREPEAT9( macro, data) macro( 9, data) +#define MREPEAT11( macro, data) MREPEAT10( macro, data) macro( 10, data) +#define MREPEAT12( macro, data) MREPEAT11( macro, data) macro( 11, data) +#define MREPEAT13( macro, data) MREPEAT12( macro, data) macro( 12, data) +#define MREPEAT14( macro, data) MREPEAT13( macro, data) macro( 13, data) +#define MREPEAT15( macro, data) MREPEAT14( macro, data) macro( 14, data) +#define MREPEAT16( macro, data) MREPEAT15( macro, data) macro( 15, data) +#define MREPEAT17( macro, data) MREPEAT16( macro, data) macro( 16, data) +#define MREPEAT18( macro, data) MREPEAT17( macro, data) macro( 17, data) +#define MREPEAT19( macro, data) MREPEAT18( macro, data) macro( 18, data) +#define MREPEAT20( macro, data) MREPEAT19( macro, data) macro( 19, data) +#define MREPEAT21( macro, data) MREPEAT20( macro, data) macro( 20, data) +#define MREPEAT22( macro, data) MREPEAT21( macro, data) macro( 21, data) +#define MREPEAT23( macro, data) MREPEAT22( macro, data) macro( 22, data) +#define MREPEAT24( macro, data) MREPEAT23( macro, data) macro( 23, data) +#define MREPEAT25( macro, data) MREPEAT24( macro, data) macro( 24, data) +#define MREPEAT26( macro, data) MREPEAT25( macro, data) macro( 25, data) +#define MREPEAT27( macro, data) MREPEAT26( macro, data) macro( 26, data) +#define MREPEAT28( macro, data) MREPEAT27( macro, data) macro( 27, data) +#define MREPEAT29( macro, data) MREPEAT28( macro, data) macro( 28, data) +#define MREPEAT30( macro, data) MREPEAT29( macro, data) macro( 29, data) +#define MREPEAT31( macro, data) MREPEAT30( macro, data) macro( 30, data) +#define MREPEAT32( macro, data) MREPEAT31( macro, data) macro( 31, data) +#define MREPEAT33( macro, data) MREPEAT32( macro, data) macro( 32, data) +#define MREPEAT34( macro, data) MREPEAT33( macro, data) macro( 33, data) +#define MREPEAT35( macro, data) MREPEAT34( macro, data) macro( 34, data) +#define MREPEAT36( macro, data) MREPEAT35( macro, data) macro( 35, data) +#define MREPEAT37( macro, data) MREPEAT36( macro, data) macro( 36, data) +#define MREPEAT38( macro, data) MREPEAT37( macro, data) macro( 37, data) +#define MREPEAT39( macro, data) MREPEAT38( macro, data) macro( 38, data) +#define MREPEAT40( macro, data) MREPEAT39( macro, data) macro( 39, data) +#define MREPEAT41( macro, data) MREPEAT40( macro, data) macro( 40, data) +#define MREPEAT42( macro, data) MREPEAT41( macro, data) macro( 41, data) +#define MREPEAT43( macro, data) MREPEAT42( macro, data) macro( 42, data) +#define MREPEAT44( macro, data) MREPEAT43( macro, data) macro( 43, data) +#define MREPEAT45( macro, data) MREPEAT44( macro, data) macro( 44, data) +#define MREPEAT46( macro, data) MREPEAT45( macro, data) macro( 45, data) +#define MREPEAT47( macro, data) MREPEAT46( macro, data) macro( 46, data) +#define MREPEAT48( macro, data) MREPEAT47( macro, data) macro( 47, data) +#define MREPEAT49( macro, data) MREPEAT48( macro, data) macro( 48, data) +#define MREPEAT50( macro, data) MREPEAT49( macro, data) macro( 49, data) +#define MREPEAT51( macro, data) MREPEAT50( macro, data) macro( 50, data) +#define MREPEAT52( macro, data) MREPEAT51( macro, data) macro( 51, data) +#define MREPEAT53( macro, data) MREPEAT52( macro, data) macro( 52, data) +#define MREPEAT54( macro, data) MREPEAT53( macro, data) macro( 53, data) +#define MREPEAT55( macro, data) MREPEAT54( macro, data) macro( 54, data) +#define MREPEAT56( macro, data) MREPEAT55( macro, data) macro( 55, data) +#define MREPEAT57( macro, data) MREPEAT56( macro, data) macro( 56, data) +#define MREPEAT58( macro, data) MREPEAT57( macro, data) macro( 57, data) +#define MREPEAT59( macro, data) MREPEAT58( macro, data) macro( 58, data) +#define MREPEAT60( macro, data) MREPEAT59( macro, data) macro( 59, data) +#define MREPEAT61( macro, data) MREPEAT60( macro, data) macro( 60, data) +#define MREPEAT62( macro, data) MREPEAT61( macro, data) macro( 61, data) +#define MREPEAT63( macro, data) MREPEAT62( macro, data) macro( 62, data) +#define MREPEAT64( macro, data) MREPEAT63( macro, data) macro( 63, data) +#define MREPEAT65( macro, data) MREPEAT64( macro, data) macro( 64, data) +#define MREPEAT66( macro, data) MREPEAT65( macro, data) macro( 65, data) +#define MREPEAT67( macro, data) MREPEAT66( macro, data) macro( 66, data) +#define MREPEAT68( macro, data) MREPEAT67( macro, data) macro( 67, data) +#define MREPEAT69( macro, data) MREPEAT68( macro, data) macro( 68, data) +#define MREPEAT70( macro, data) MREPEAT69( macro, data) macro( 69, data) +#define MREPEAT71( macro, data) MREPEAT70( macro, data) macro( 70, data) +#define MREPEAT72( macro, data) MREPEAT71( macro, data) macro( 71, data) +#define MREPEAT73( macro, data) MREPEAT72( macro, data) macro( 72, data) +#define MREPEAT74( macro, data) MREPEAT73( macro, data) macro( 73, data) +#define MREPEAT75( macro, data) MREPEAT74( macro, data) macro( 74, data) +#define MREPEAT76( macro, data) MREPEAT75( macro, data) macro( 75, data) +#define MREPEAT77( macro, data) MREPEAT76( macro, data) macro( 76, data) +#define MREPEAT78( macro, data) MREPEAT77( macro, data) macro( 77, data) +#define MREPEAT79( macro, data) MREPEAT78( macro, data) macro( 78, data) +#define MREPEAT80( macro, data) MREPEAT79( macro, data) macro( 79, data) +#define MREPEAT81( macro, data) MREPEAT80( macro, data) macro( 80, data) +#define MREPEAT82( macro, data) MREPEAT81( macro, data) macro( 81, data) +#define MREPEAT83( macro, data) MREPEAT82( macro, data) macro( 82, data) +#define MREPEAT84( macro, data) MREPEAT83( macro, data) macro( 83, data) +#define MREPEAT85( macro, data) MREPEAT84( macro, data) macro( 84, data) +#define MREPEAT86( macro, data) MREPEAT85( macro, data) macro( 85, data) +#define MREPEAT87( macro, data) MREPEAT86( macro, data) macro( 86, data) +#define MREPEAT88( macro, data) MREPEAT87( macro, data) macro( 87, data) +#define MREPEAT89( macro, data) MREPEAT88( macro, data) macro( 88, data) +#define MREPEAT90( macro, data) MREPEAT89( macro, data) macro( 89, data) +#define MREPEAT91( macro, data) MREPEAT90( macro, data) macro( 90, data) +#define MREPEAT92( macro, data) MREPEAT91( macro, data) macro( 91, data) +#define MREPEAT93( macro, data) MREPEAT92( macro, data) macro( 92, data) +#define MREPEAT94( macro, data) MREPEAT93( macro, data) macro( 93, data) +#define MREPEAT95( macro, data) MREPEAT94( macro, data) macro( 94, data) +#define MREPEAT96( macro, data) MREPEAT95( macro, data) macro( 95, data) +#define MREPEAT97( macro, data) MREPEAT96( macro, data) macro( 96, data) +#define MREPEAT98( macro, data) MREPEAT97( macro, data) macro( 97, data) +#define MREPEAT99( macro, data) MREPEAT98( macro, data) macro( 98, data) +#define MREPEAT100(macro, data) MREPEAT99( macro, data) macro( 99, data) +#define MREPEAT101(macro, data) MREPEAT100(macro, data) macro(100, data) +#define MREPEAT102(macro, data) MREPEAT101(macro, data) macro(101, data) +#define MREPEAT103(macro, data) MREPEAT102(macro, data) macro(102, data) +#define MREPEAT104(macro, data) MREPEAT103(macro, data) macro(103, data) +#define MREPEAT105(macro, data) MREPEAT104(macro, data) macro(104, data) +#define MREPEAT106(macro, data) MREPEAT105(macro, data) macro(105, data) +#define MREPEAT107(macro, data) MREPEAT106(macro, data) macro(106, data) +#define MREPEAT108(macro, data) MREPEAT107(macro, data) macro(107, data) +#define MREPEAT109(macro, data) MREPEAT108(macro, data) macro(108, data) +#define MREPEAT110(macro, data) MREPEAT109(macro, data) macro(109, data) +#define MREPEAT111(macro, data) MREPEAT110(macro, data) macro(110, data) +#define MREPEAT112(macro, data) MREPEAT111(macro, data) macro(111, data) +#define MREPEAT113(macro, data) MREPEAT112(macro, data) macro(112, data) +#define MREPEAT114(macro, data) MREPEAT113(macro, data) macro(113, data) +#define MREPEAT115(macro, data) MREPEAT114(macro, data) macro(114, data) +#define MREPEAT116(macro, data) MREPEAT115(macro, data) macro(115, data) +#define MREPEAT117(macro, data) MREPEAT116(macro, data) macro(116, data) +#define MREPEAT118(macro, data) MREPEAT117(macro, data) macro(117, data) +#define MREPEAT119(macro, data) MREPEAT118(macro, data) macro(118, data) +#define MREPEAT120(macro, data) MREPEAT119(macro, data) macro(119, data) +#define MREPEAT121(macro, data) MREPEAT120(macro, data) macro(120, data) +#define MREPEAT122(macro, data) MREPEAT121(macro, data) macro(121, data) +#define MREPEAT123(macro, data) MREPEAT122(macro, data) macro(122, data) +#define MREPEAT124(macro, data) MREPEAT123(macro, data) macro(123, data) +#define MREPEAT125(macro, data) MREPEAT124(macro, data) macro(124, data) +#define MREPEAT126(macro, data) MREPEAT125(macro, data) macro(125, data) +#define MREPEAT127(macro, data) MREPEAT126(macro, data) macro(126, data) +#define MREPEAT128(macro, data) MREPEAT127(macro, data) macro(127, data) +#define MREPEAT129(macro, data) MREPEAT128(macro, data) macro(128, data) +#define MREPEAT130(macro, data) MREPEAT129(macro, data) macro(129, data) +#define MREPEAT131(macro, data) MREPEAT130(macro, data) macro(130, data) +#define MREPEAT132(macro, data) MREPEAT131(macro, data) macro(131, data) +#define MREPEAT133(macro, data) MREPEAT132(macro, data) macro(132, data) +#define MREPEAT134(macro, data) MREPEAT133(macro, data) macro(133, data) +#define MREPEAT135(macro, data) MREPEAT134(macro, data) macro(134, data) +#define MREPEAT136(macro, data) MREPEAT135(macro, data) macro(135, data) +#define MREPEAT137(macro, data) MREPEAT136(macro, data) macro(136, data) +#define MREPEAT138(macro, data) MREPEAT137(macro, data) macro(137, data) +#define MREPEAT139(macro, data) MREPEAT138(macro, data) macro(138, data) +#define MREPEAT140(macro, data) MREPEAT139(macro, data) macro(139, data) +#define MREPEAT141(macro, data) MREPEAT140(macro, data) macro(140, data) +#define MREPEAT142(macro, data) MREPEAT141(macro, data) macro(141, data) +#define MREPEAT143(macro, data) MREPEAT142(macro, data) macro(142, data) +#define MREPEAT144(macro, data) MREPEAT143(macro, data) macro(143, data) +#define MREPEAT145(macro, data) MREPEAT144(macro, data) macro(144, data) +#define MREPEAT146(macro, data) MREPEAT145(macro, data) macro(145, data) +#define MREPEAT147(macro, data) MREPEAT146(macro, data) macro(146, data) +#define MREPEAT148(macro, data) MREPEAT147(macro, data) macro(147, data) +#define MREPEAT149(macro, data) MREPEAT148(macro, data) macro(148, data) +#define MREPEAT150(macro, data) MREPEAT149(macro, data) macro(149, data) +#define MREPEAT151(macro, data) MREPEAT150(macro, data) macro(150, data) +#define MREPEAT152(macro, data) MREPEAT151(macro, data) macro(151, data) +#define MREPEAT153(macro, data) MREPEAT152(macro, data) macro(152, data) +#define MREPEAT154(macro, data) MREPEAT153(macro, data) macro(153, data) +#define MREPEAT155(macro, data) MREPEAT154(macro, data) macro(154, data) +#define MREPEAT156(macro, data) MREPEAT155(macro, data) macro(155, data) +#define MREPEAT157(macro, data) MREPEAT156(macro, data) macro(156, data) +#define MREPEAT158(macro, data) MREPEAT157(macro, data) macro(157, data) +#define MREPEAT159(macro, data) MREPEAT158(macro, data) macro(158, data) +#define MREPEAT160(macro, data) MREPEAT159(macro, data) macro(159, data) +#define MREPEAT161(macro, data) MREPEAT160(macro, data) macro(160, data) +#define MREPEAT162(macro, data) MREPEAT161(macro, data) macro(161, data) +#define MREPEAT163(macro, data) MREPEAT162(macro, data) macro(162, data) +#define MREPEAT164(macro, data) MREPEAT163(macro, data) macro(163, data) +#define MREPEAT165(macro, data) MREPEAT164(macro, data) macro(164, data) +#define MREPEAT166(macro, data) MREPEAT165(macro, data) macro(165, data) +#define MREPEAT167(macro, data) MREPEAT166(macro, data) macro(166, data) +#define MREPEAT168(macro, data) MREPEAT167(macro, data) macro(167, data) +#define MREPEAT169(macro, data) MREPEAT168(macro, data) macro(168, data) +#define MREPEAT170(macro, data) MREPEAT169(macro, data) macro(169, data) +#define MREPEAT171(macro, data) MREPEAT170(macro, data) macro(170, data) +#define MREPEAT172(macro, data) MREPEAT171(macro, data) macro(171, data) +#define MREPEAT173(macro, data) MREPEAT172(macro, data) macro(172, data) +#define MREPEAT174(macro, data) MREPEAT173(macro, data) macro(173, data) +#define MREPEAT175(macro, data) MREPEAT174(macro, data) macro(174, data) +#define MREPEAT176(macro, data) MREPEAT175(macro, data) macro(175, data) +#define MREPEAT177(macro, data) MREPEAT176(macro, data) macro(176, data) +#define MREPEAT178(macro, data) MREPEAT177(macro, data) macro(177, data) +#define MREPEAT179(macro, data) MREPEAT178(macro, data) macro(178, data) +#define MREPEAT180(macro, data) MREPEAT179(macro, data) macro(179, data) +#define MREPEAT181(macro, data) MREPEAT180(macro, data) macro(180, data) +#define MREPEAT182(macro, data) MREPEAT181(macro, data) macro(181, data) +#define MREPEAT183(macro, data) MREPEAT182(macro, data) macro(182, data) +#define MREPEAT184(macro, data) MREPEAT183(macro, data) macro(183, data) +#define MREPEAT185(macro, data) MREPEAT184(macro, data) macro(184, data) +#define MREPEAT186(macro, data) MREPEAT185(macro, data) macro(185, data) +#define MREPEAT187(macro, data) MREPEAT186(macro, data) macro(186, data) +#define MREPEAT188(macro, data) MREPEAT187(macro, data) macro(187, data) +#define MREPEAT189(macro, data) MREPEAT188(macro, data) macro(188, data) +#define MREPEAT190(macro, data) MREPEAT189(macro, data) macro(189, data) +#define MREPEAT191(macro, data) MREPEAT190(macro, data) macro(190, data) +#define MREPEAT192(macro, data) MREPEAT191(macro, data) macro(191, data) +#define MREPEAT193(macro, data) MREPEAT192(macro, data) macro(192, data) +#define MREPEAT194(macro, data) MREPEAT193(macro, data) macro(193, data) +#define MREPEAT195(macro, data) MREPEAT194(macro, data) macro(194, data) +#define MREPEAT196(macro, data) MREPEAT195(macro, data) macro(195, data) +#define MREPEAT197(macro, data) MREPEAT196(macro, data) macro(196, data) +#define MREPEAT198(macro, data) MREPEAT197(macro, data) macro(197, data) +#define MREPEAT199(macro, data) MREPEAT198(macro, data) macro(198, data) +#define MREPEAT200(macro, data) MREPEAT199(macro, data) macro(199, data) +#define MREPEAT201(macro, data) MREPEAT200(macro, data) macro(200, data) +#define MREPEAT202(macro, data) MREPEAT201(macro, data) macro(201, data) +#define MREPEAT203(macro, data) MREPEAT202(macro, data) macro(202, data) +#define MREPEAT204(macro, data) MREPEAT203(macro, data) macro(203, data) +#define MREPEAT205(macro, data) MREPEAT204(macro, data) macro(204, data) +#define MREPEAT206(macro, data) MREPEAT205(macro, data) macro(205, data) +#define MREPEAT207(macro, data) MREPEAT206(macro, data) macro(206, data) +#define MREPEAT208(macro, data) MREPEAT207(macro, data) macro(207, data) +#define MREPEAT209(macro, data) MREPEAT208(macro, data) macro(208, data) +#define MREPEAT210(macro, data) MREPEAT209(macro, data) macro(209, data) +#define MREPEAT211(macro, data) MREPEAT210(macro, data) macro(210, data) +#define MREPEAT212(macro, data) MREPEAT211(macro, data) macro(211, data) +#define MREPEAT213(macro, data) MREPEAT212(macro, data) macro(212, data) +#define MREPEAT214(macro, data) MREPEAT213(macro, data) macro(213, data) +#define MREPEAT215(macro, data) MREPEAT214(macro, data) macro(214, data) +#define MREPEAT216(macro, data) MREPEAT215(macro, data) macro(215, data) +#define MREPEAT217(macro, data) MREPEAT216(macro, data) macro(216, data) +#define MREPEAT218(macro, data) MREPEAT217(macro, data) macro(217, data) +#define MREPEAT219(macro, data) MREPEAT218(macro, data) macro(218, data) +#define MREPEAT220(macro, data) MREPEAT219(macro, data) macro(219, data) +#define MREPEAT221(macro, data) MREPEAT220(macro, data) macro(220, data) +#define MREPEAT222(macro, data) MREPEAT221(macro, data) macro(221, data) +#define MREPEAT223(macro, data) MREPEAT222(macro, data) macro(222, data) +#define MREPEAT224(macro, data) MREPEAT223(macro, data) macro(223, data) +#define MREPEAT225(macro, data) MREPEAT224(macro, data) macro(224, data) +#define MREPEAT226(macro, data) MREPEAT225(macro, data) macro(225, data) +#define MREPEAT227(macro, data) MREPEAT226(macro, data) macro(226, data) +#define MREPEAT228(macro, data) MREPEAT227(macro, data) macro(227, data) +#define MREPEAT229(macro, data) MREPEAT228(macro, data) macro(228, data) +#define MREPEAT230(macro, data) MREPEAT229(macro, data) macro(229, data) +#define MREPEAT231(macro, data) MREPEAT230(macro, data) macro(230, data) +#define MREPEAT232(macro, data) MREPEAT231(macro, data) macro(231, data) +#define MREPEAT233(macro, data) MREPEAT232(macro, data) macro(232, data) +#define MREPEAT234(macro, data) MREPEAT233(macro, data) macro(233, data) +#define MREPEAT235(macro, data) MREPEAT234(macro, data) macro(234, data) +#define MREPEAT236(macro, data) MREPEAT235(macro, data) macro(235, data) +#define MREPEAT237(macro, data) MREPEAT236(macro, data) macro(236, data) +#define MREPEAT238(macro, data) MREPEAT237(macro, data) macro(237, data) +#define MREPEAT239(macro, data) MREPEAT238(macro, data) macro(238, data) +#define MREPEAT240(macro, data) MREPEAT239(macro, data) macro(239, data) +#define MREPEAT241(macro, data) MREPEAT240(macro, data) macro(240, data) +#define MREPEAT242(macro, data) MREPEAT241(macro, data) macro(241, data) +#define MREPEAT243(macro, data) MREPEAT242(macro, data) macro(242, data) +#define MREPEAT244(macro, data) MREPEAT243(macro, data) macro(243, data) +#define MREPEAT245(macro, data) MREPEAT244(macro, data) macro(244, data) +#define MREPEAT246(macro, data) MREPEAT245(macro, data) macro(245, data) +#define MREPEAT247(macro, data) MREPEAT246(macro, data) macro(246, data) +#define MREPEAT248(macro, data) MREPEAT247(macro, data) macro(247, data) +#define MREPEAT249(macro, data) MREPEAT248(macro, data) macro(248, data) +#define MREPEAT250(macro, data) MREPEAT249(macro, data) macro(249, data) +#define MREPEAT251(macro, data) MREPEAT250(macro, data) macro(250, data) +#define MREPEAT252(macro, data) MREPEAT251(macro, data) macro(251, data) +#define MREPEAT253(macro, data) MREPEAT252(macro, data) macro(252, data) +#define MREPEAT254(macro, data) MREPEAT253(macro, data) macro(253, data) +#define MREPEAT255(macro, data) MREPEAT254(macro, data) macro(254, data) +#define MREPEAT256(macro, data) MREPEAT255(macro, data) macro(255, data) + +/** + * \} + */ + +#endif // _MREPEAT_H_ diff --git a/DSTAT-temp/src/asf/xmega/utils/preprocessor/preprocessor.h b/DSTAT-temp/src/asf/xmega/utils/preprocessor/preprocessor.h new file mode 100644 index 0000000..526d217 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/preprocessor/preprocessor.h @@ -0,0 +1,51 @@ +/** + * \file + * + * \brief Preprocessor utils. + * + * Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef _PREPROCESSOR_H_ +#define _PREPROCESSOR_H_ + +#include "tpaste.h" +#include "stringz.h" +#include "mrepeat.h" + + +#endif // _PREPROCESSOR_H_ diff --git a/DSTAT-temp/src/asf/xmega/utils/preprocessor/stringz.h b/DSTAT-temp/src/asf/xmega/utils/preprocessor/stringz.h new file mode 100644 index 0000000..11ca5d9 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/preprocessor/stringz.h @@ -0,0 +1,81 @@ +/** + * \file + * + * \brief Preprocessor stringizing utils. + * + * Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef _STRINGZ_H_ +#define _STRINGZ_H_ + +/** + * \defgroup group_xmega_utils_stringz Stringize + * + * \ingroup group_xmega_utils + * + * \{ + */ + +/*! \brief Stringize. + * + * Stringize a preprocessing token, this token being allowed to be \#defined. + * + * May be used only within macros with the token passed as an argument if the token is \#defined. + * + * For example, writing STRINGZ(PIN) within a macro \#defined by PIN_NAME(PIN) + * and invoked as PIN_NAME(PIN0) with PIN0 \#defined as A0 is equivalent to + * writing "A0". + */ +#define STRINGZ(x) #x + +/*! \brief Absolute stringize. + * + * Stringize a preprocessing token, this token being allowed to be \#defined. + * + * No restriction of use if the token is \#defined. + * + * For example, writing ASTRINGZ(PIN0) anywhere with PIN0 \#defined as A0 is + * equivalent to writing "A0". + */ +#define ASTRINGZ(x) STRINGZ(x) + +/** + * \} + */ + +#endif // _STRINGZ_H_ diff --git a/DSTAT-temp/src/asf/xmega/utils/preprocessor/tpaste.h b/DSTAT-temp/src/asf/xmega/utils/preprocessor/tpaste.h new file mode 100644 index 0000000..335ea1e --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/preprocessor/tpaste.h @@ -0,0 +1,101 @@ +/** + * \file + * + * \brief Preprocessor token pasting utils. + * + * Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef _TPASTE_H_ +#define _TPASTE_H_ + +/** + * \defgroup group_xmega_utils_tpaste Token Paste + * + * \ingroup group_xmega_utils + * + * \{ + */ + +/*! \name Token Paste + * + * Paste N preprocessing tokens together, these tokens being allowed to be \#defined. + * + * May be used only within macros with the tokens passed as arguments if the tokens are \#defined. + * + * For example, writing TPASTE2(U, WIDTH) within a macro \#defined by + * UTYPE(WIDTH) and invoked as UTYPE(UL_WIDTH) with UL_WIDTH \#defined as 32 is + * equivalent to writing U32. + */ +//! @{ +#define TPASTE2( a, b) a##b +#define TPASTE3( a, b, c) a##b##c +#define TPASTE4( a, b, c, d) a##b##c##d +#define TPASTE5( a, b, c, d, e) a##b##c##d##e +#define TPASTE6( a, b, c, d, e, f) a##b##c##d##e##f +#define TPASTE7( a, b, c, d, e, f, g) a##b##c##d##e##f##g +#define TPASTE8( a, b, c, d, e, f, g, h) a##b##c##d##e##f##g##h +#define TPASTE9( a, b, c, d, e, f, g, h, i) a##b##c##d##e##f##g##h##i +#define TPASTE10(a, b, c, d, e, f, g, h, i, j) a##b##c##d##e##f##g##h##i##j +//! @} + +/*! \name Absolute Token Paste + * + * Paste N preprocessing tokens together, these tokens being allowed to be \#defined. + * + * No restriction of use if the tokens are \#defined. + * + * For example, writing ATPASTE2(U, UL_WIDTH) anywhere with UL_WIDTH \#defined + * as 32 is equivalent to writing U32. + */ +//! @{ +#define ATPASTE2( a, b) TPASTE2( a, b) +#define ATPASTE3( a, b, c) TPASTE3( a, b, c) +#define ATPASTE4( a, b, c, d) TPASTE4( a, b, c, d) +#define ATPASTE5( a, b, c, d, e) TPASTE5( a, b, c, d, e) +#define ATPASTE6( a, b, c, d, e, f) TPASTE6( a, b, c, d, e, f) +#define ATPASTE7( a, b, c, d, e, f, g) TPASTE7( a, b, c, d, e, f, g) +#define ATPASTE8( a, b, c, d, e, f, g, h) TPASTE8( a, b, c, d, e, f, g, h) +#define ATPASTE9( a, b, c, d, e, f, g, h, i) TPASTE9( a, b, c, d, e, f, g, h, i) +#define ATPASTE10(a, b, c, d, e, f, g, h, i, j) TPASTE10(a, b, c, d, e, f, g, h, i, j) +//! @} + +/** + * \} + */ + +#endif // _TPASTE_H_ diff --git a/DSTAT-temp/src/asf/xmega/utils/progmem.h b/DSTAT-temp/src/asf/xmega/utils/progmem.h new file mode 100644 index 0000000..b249766 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/progmem.h @@ -0,0 +1,99 @@ +/** + * \file + * + * \brief Program memory access + * + * Copyright (c) 2010 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef UTILS_PROGMEM_H +#define UTILS_PROGMEM_H + +/** + * \defgroup group_xmega_utils_progmem Program memory + * + * \ingroup group_xmega_utils + * + * \{ + */ + +/*! \name Program memory + * + * Macros for locating and accessing data in program memory. + * + * @{ + */ +#if defined(__GNUC__) || defined(__DOXYGEN__) +# include +# define PROGMEM_LOCATION(type, name, loc) \ + type name __attribute__((section (#loc))) +# define PROGMEM_DECLARE(type, name) const type name __attribute__((__progmem__)) +# define PROGMEM_STRING(x) PSTR(x) +# define PROGMEM_STRING_T PGM_P +# define PROGMEM_T const +# define PROGMEM_PTR_T const * +# define PROGMEM_BYTE_ARRAY_T uint8_t* +# define PROGMEM_WORD_ARRAY_T uint16_t* +# define PROGMEM_READ_BYTE(x) pgm_read_byte(x) +# define PROGMEM_READ_WORD(x) pgm_read_word(x) + +#elif defined(__ICCAVR__) +# include +# ifndef __HAS_ELPM__ +# define _MEMATTR_ASF __flash +# else /* __HAS_ELPM__ */ +# define _MEMATTR_ASF __hugeflash +# endif /* __HAS_ELPM__ */ +# define PROGMEM_LOCATION(type, name, loc) const _MEMATTR_ASF type name @ loc +# define PROGMEM_DECLARE(type, name) _MEMATTR_ASF type name +# define PROGMEM_STRING(x) ((_MEMATTR_ASF const char *)(x)) +# define PROGMEM_STRING_T char const _MEMATTR_ASF * +# define PROGMEM_T const _MEMATTR_ASF +# define PROGMEM_PTR_T const _MEMATTR_ASF * +# define PROGMEM_BYTE_ARRAY_T uint8_t const _MEMATTR_ASF * +# define PROGMEM_WORD_ARRAY_T uint16_t const _MEMATTR_ASF * +# define PROGMEM_READ_BYTE(x) *(x) +# define PROGMEM_READ_WORD(x) *(x) +#endif +//! @} + +/** + * \} + */ + +#endif /* UTILS_PROGMEM_H */ diff --git a/DSTAT-temp/src/asf/xmega/utils/status_codes.h b/DSTAT-temp/src/asf/xmega/utils/status_codes.h new file mode 100644 index 0000000..bdd4a52 --- /dev/null +++ b/DSTAT-temp/src/asf/xmega/utils/status_codes.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Status code definitions. + * + * This file defines various status codes returned by functions, + * indicating success or failure as well as what kind of failure. + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef STATUS_CODES_H_INCLUDED +#define STATUS_CODES_H_INCLUDED + +/** + * \defgroup group_xmega_utils_status_codes Status Codes + * + * \ingroup group_xmega_utils + * + * \{ + */ + +/* Note: this is a local workaround to avoid a pre-processor clash due to the + * lwIP macro ERR_TIMEOUT. */ +#if defined(__LWIP_ERR_H__) && defined(ERR_TIMEOUT) +#if (ERR_TIMEOUT != -3) + +/* Internal check to make sure that the later restore of lwIP's ERR_TIMEOUT + * macro is set to the correct value. Note that it is highly improbable that + * this value ever changes in lwIP. */ +#error ASF developers: check lwip err.h new value for ERR_TIMEOUT +#endif +#undef ERR_TIMEOUT +#endif + +/** + * Status code that may be returned by shell commands and protocol + * implementations. + * + * \note Any change to these status codes and the corresponding + * message strings is strictly forbidden. New codes can be added, + * however, but make sure that any message string tables are updated + * at the same time. + */ +enum status_code { + STATUS_OK = 0, //!< Success + ERR_IO_ERROR = -1, //!< I/O error + ERR_FLUSHED = -2, //!< Request flushed from queue + ERR_TIMEOUT = -3, //!< Operation timed out + ERR_BAD_DATA = -4, //!< Data integrity check failed + ERR_PROTOCOL = -5, //!< Protocol error + ERR_UNSUPPORTED_DEV = -6, //!< Unsupported device + ERR_NO_MEMORY = -7, //!< Insufficient memory + ERR_INVALID_ARG = -8, //!< Invalid argument + ERR_BAD_ADDRESS = -9, //!< Bad address + ERR_BUSY = -10, //!< Resource is busy + ERR_BAD_FORMAT = -11, //!< Data format not recognized + + /** + * \brief Operation in progress + * + * This status code is for driver-internal use when an operation + * is currently being performed. + * + * \note Drivers should never return this status code to any + * callers. It is strictly for internal use. + */ + OPERATION_IN_PROGRESS = -128, +}; + +typedef enum status_code status_code_t; + +#if defined(__LWIP_ERR_H__) +#define ERR_TIMEOUT -3 +#endif + +/** + * \} + */ + +#endif /* STATUS_CODES_H_INCLUDED */ diff --git a/DSTAT-temp/src/config/conf_board.h b/DSTAT-temp/src/config/conf_board.h new file mode 100644 index 0000000..80fd2f0 --- /dev/null +++ b/DSTAT-temp/src/config/conf_board.h @@ -0,0 +1,11 @@ +/** + * \file + * + * \brief User board configuration template + * + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/DSTAT-temp/src/config/conf_clock.h b/DSTAT-temp/src/config/conf_clock.h new file mode 100644 index 0000000..1843905 --- /dev/null +++ b/DSTAT-temp/src/config/conf_clock.h @@ -0,0 +1,98 @@ +/** + * \file + * + * \brief Chip-specific system clock manager configuration + * + * Copyright (c) 2011-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef CONF_CLOCK_H_INCLUDED +#define CONF_CLOCK_H_INCLUDED + +//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC2MHZ +#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC32MHZ +//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC32KHZ +//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_XOSC +//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLL + +/* Fbus = Fsys / (2 ^ BUS_div) */ +#define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_1 +#define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_1 + +//#define CONFIG_PLL0_SOURCE PLL_SRC_XOSC +//#define CONFIG_PLL0_SOURCE PLL_SRC_RC2MHZ +//#define CONFIG_PLL0_SOURCE PLL_SRC_RC32MHZ + +/* Fpll = (Fclk * PLL_mul) / PLL_div */ +//#define CONFIG_PLL0_MUL (24000000UL / BOARD_XOSC_HZ) +//#define CONFIG_PLL0_DIV 1 + +/* External oscillator frequency range */ +/** 0.4 to 2 MHz frequency range */ +//#define CONFIG_XOSC_RANGE XOSC_RANGE_04TO2 +/** 2 to 9 MHz frequency range */ +//#define CONFIG_XOSC_RANGE XOSC_RANGE_2TO9 +/** 9 to 12 MHz frequency range */ +//#define CONFIG_XOSC_RANGE XOSC_RANGE_9TO12 +/** 12 to 16 MHz frequency range */ +//#define CONFIG_XOSC_RANGE XOSC_RANGE_12TO16 + +/* DFLL autocalibration */ +//#define CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC OSC_ID_RC32KHZ +//#define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC OSC_ID_XOSC + +/* The following example clock configuration definitions can be used in XMEGA + * devices that contain a USB controller. It configures the USB controller clock + * source to use the internal (nominally) 32MHz RC oscillator, up-calibrated to + * run at 48MHz via the periodic 1ms USB Start Of Frame packets sent by the + * host. The USB controller requires 48MHz for Full Speed operation, or 6MHz + * for USB Low Speed operation. + * + * Note that when the 32MHz RC oscillator is tuned to 48MHz, it cannot be used + * directly as the system clock source; it must either be prescaled down to a + * speed below the maximum operating frequency given in the datasheet, or an + * alternative clock source (e.g. the internal 2MHz RC Oscillator, multiplied + * to a higher frequency via the internal PLL module) must be used instead. + */ +#define CONFIG_USBCLK_SOURCE USBCLK_SRC_RCOSC +#define CONFIG_OSC_RC32_CAL 48000000UL +#define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC OSC_ID_USBSOF + +/* Use to enable and select RTC clock source */ +//#define CONFIG_RTC_SOURCE SYSCLK_RTCSRC_ULP + +#endif /* CONF_CLOCK_H_INCLUDED */ diff --git a/DSTAT-temp/src/config/conf_rtc.h b/DSTAT-temp/src/config/conf_rtc.h new file mode 100644 index 0000000..22efd92 --- /dev/null +++ b/DSTAT-temp/src/config/conf_rtc.h @@ -0,0 +1,50 @@ +/** + * \file + * + * \brief RTC configuration + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef CONF_RTC_H +#define CONF_RTC_H + +#define CONFIG_RTC_PRESCALER RTC_PRESCALER_DIV1024_gc +#define CONFIG_RTC_COMPARE_INT_LEVEL RTC_COMPINTLVL_LO_gc +#define CONFIG_RTC_OVERFLOW_INT_LEVEL RTC_OVFINTLVL_LO_gc + +#endif /* CONF_RTC_H */ diff --git a/DSTAT-temp/src/config/conf_sleepmgr.h b/DSTAT-temp/src/config/conf_sleepmgr.h new file mode 100644 index 0000000..1e257df --- /dev/null +++ b/DSTAT-temp/src/config/conf_sleepmgr.h @@ -0,0 +1,49 @@ +/** + * \file + * + * \brief Chip-specific sleep manager configuration + * + * Copyright (c) 2010 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef CONF_SLEEPMGR_H +#define CONF_SLEEPMGR_H + +// Sleep manager options +#define CONFIG_SLEEPMGR_ENABLE + +#endif /* CONF_SLEEPMGR_H */ diff --git a/DSTAT-temp/src/config/conf_usart_spi.h b/DSTAT-temp/src/config/conf_usart_spi.h new file mode 100644 index 0000000..b5360e4 --- /dev/null +++ b/DSTAT-temp/src/config/conf_usart_spi.h @@ -0,0 +1,47 @@ +/** + * \file ********************************************************************* + * + * \brief Spi Master configuration for spi example + * + * Copyright (c) 2011 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef CONF_USART_SPI_H_INCLUDED +#define CONF_USART_SPI_H_INCLUDED + + +#endif /* CONF_USART_SPI_H_INCLUDED */ diff --git a/DSTAT-temp/src/config/conf_usb.h b/DSTAT-temp/src/config/conf_usb.h new file mode 100644 index 0000000..2cbf82c --- /dev/null +++ b/DSTAT-temp/src/config/conf_usb.h @@ -0,0 +1,165 @@ +/** + * \file + * + * \brief USB configuration file for CDC application + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef _CONF_USB_H_ +#define _CONF_USB_H_ + +#include "compiler.h" + +/** + * USB Device Configuration + * @{ + */ + +//! Device definition (mandatory) +#define USB_DEVICE_VENDOR_ID 0x0042 +#define USB_DEVICE_PRODUCT_ID 0x0002 +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 1 +#define USB_DEVICE_POWER 200 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#define USB_DEVICE_MANUFACTURE_NAME "Wheeler Lab" +#define USB_DEVICE_PRODUCT_NAME "DStat" +// #define USB_DEVICE_SERIAL_NAME "12...EF" + + +/** + * Device speeds support + * Low speed not supported by CDC + * @{ + */ +//! To authorize the High speed +#if (UC3A3||UC3A4) +#define USB_DEVICE_HS_SUPPORT +#endif +//@} + + +/** + * USB Device Callbacks definitions (Optional) + * @{ + */ +// #define UDC_VBUS_EVENT(b_vbus_high) user_callback_vbus_action(b_vbus_high) +// extern void user_callback_vbus_action(bool b_vbus_high); +// #define UDC_SOF_EVENT() user_callback_sof_action() +// extern void user_callback_sof_action(void); +// #define UDC_SUSPEND_EVENT() user_callback_suspend_action() +// extern void user_callback_suspend_action(void); +// #define UDC_RESUME_EVENT() user_callback_resume_action() +// extern void user_callback_resume_action(void); +// Mandatory when USB_DEVICE_ATTR authorizes remote wakeup feature +// #define UDC_REMOTEWAKEUP_ENABLE() user_callback_remotewakeup_enable() +// extern void user_callback_remotewakeup_enable(void); +// #define UDC_REMOTEWAKEUP_DISABLE() user_callback_remotewakeup_disable() +// extern void user_callback_remotewakeup_disable(void); +// When a extra string descriptor must be supported +// other than manufacturer, product and serial string +// #define UDC_GET_EXTRA_STRING() +//@} + +//@} + + +/** + * USB Interface Configuration + * @{ + */ +/** + * Configuration of CDC interface + * @{ + */ + +//! Number of communication port used (1 to 3) +#define UDI_CDC_PORT_NB 1 + +//! Interface callback definition +#define UDI_CDC_ENABLE_EXT(port) true +#define UDI_CDC_DISABLE_EXT(port) +#define UDI_CDC_RX_NOTIFY(port) +#define UDI_CDC_SET_CODING_EXT(port,cfg) +#define UDI_CDC_SET_DTR_EXT(port,set) +#define UDI_CDC_SET_RTS_EXT(port,set) +/* + * #define UDI_CDC_ENABLE_EXT(port) my_callback_cdc_enable() + * extern bool my_callback_cdc_enable(void); + * #define UDI_CDC_DISABLE_EXT(port) my_callback_cdc_disable() + * extern void my_callback_cdc_disable(void); + * #define UDI_CDC_RX_NOTIFY(port) my_callback_rx_notify(port) + * extern void my_callback_rx_notify(uint8_t port); + * #define UDI_CDC_SET_CODING_EXT(port,cfg) my_callback_config(port,cfg) + * extern void my_callback_config(uint8_t port, usb_cdc_line_coding_t * cfg); + * #define UDI_CDC_SET_DTR_EXT(port,set) my_callback_cdc_set_dtr(port,set) + * extern void my_callback_cdc_set_dtr(uint8_t port, bool b_enable); + * #define UDI_CDC_SET_RTS_EXT(port,set) my_callback_cdc_set_rts(port,set) + * extern void my_callback_cdc_set_rts(uint8_t port, bool b_enable); + */ + +//! Define it when the transfer CDC Device to Host is a low rate (<512000 bauds) +//! to reduce CDC buffers size +//#define UDI_CDC_LOW_RATE + +//! Default configuration of communication port +#define UDI_CDC_DEFAULT_RATE 1024000 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 +//@} +//@} + + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc_conf.h" + +#endif // _CONF_USB_H_ diff --git a/DSTAT-temp/src/main.c b/DSTAT-temp/src/main.c new file mode 100644 index 0000000..abffdd9 --- /dev/null +++ b/DSTAT-temp/src/main.c @@ -0,0 +1,76 @@ +/* + * main.c + * + * Created: 29/09/2012 2:13:52 AM + * Author: mdryden + */ + +#include +#include "main.h" +#include +#include +#include +#include "ads1255.h" +#include "max5443.h" + +void main(void){ + + board_init(); + pmic_init(); + + irq_initialize_vectors(); + cpu_irq_enable(); + sleepmgr_init(); + sysclk_init(); //Disables ALL peripheral clocks D: + rtc_init(); + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS); + + pmic_set_scheduling(PMIC_SCH_ROUND_ROBIN); + + stdio_usb_init(); + stdio_usb_enable(); + // printf("DStat v1 25 Jun 2012\n\r"); + + ads1255_init_pins(); + ads1255_init_module(); + ads1255_setup(ADS_BUFF_ON,ADS_DR_60,ADS_PGA_2); + // // PORTE.INT0MASK = PIN3_bm; + // // PORTE.INT1MASK = PIN3_bm; + // // PORTE.INTCTRL = PORT_INT0LVL_OFF_gc; + // // PORTE.INTCTRL = PORT_INT1LVL_OFF_gc; + PORTD.INT0MASK = PIN5_bm; + PORTD.INT1MASK = PIN5_bm; + PORTD.INTCTRL = PORT_INT0LVL_OFF_gc | PORT_INT1LVL_OFF_gc; + + max5443_init_pins(); + max5443_init_module(); + delay_ms(300); + + uint16_t input; + + // RTC.CTRL = RTC_PRESCALER_OFF_gc; + // while (RTC.STATUS & RTC_SYNCBUSY_bm); + // RTC.CNT = 0; + // RTC.PER = 0xffff; + // RTC.CTRL = RTC_PRESCALER_DIV1_gc; + + ads1255_wakeup(); + ads1255_rdatac(); + int32_t data1 = 0; + + // max5443_set_voltage1(21845); //1V + // pot_exp_start(); + + while (1){ + ads1255_standby(); + + printf("Choose Experiment type:\n\r"); + printf("Options:0, LSV:1, CV:2, SWV:3, AMP:4, EIS:5\n\r"); + printf("DStat v1.1 27 Aug 2012\n\r"); + + scanf("%u", &input); + + getchar(); + + } +} \ No newline at end of file diff --git a/DSTAT-temp/src/main.h b/DSTAT-temp/src/main.h new file mode 100644 index 0000000..0c4c577 --- /dev/null +++ b/DSTAT-temp/src/main.h @@ -0,0 +1,54 @@ +/* + * main.h + * + * Created: 06/04/2012 1:19:58 AM + * Author: mdryden + */ + + +int8_t autogainswitch(void); +void menu(uint8_t selection); +//void pot_set_gain(/*uint8_t*/ potgain_t gain); +//void pot_LP(uint8_t lponoff); +void pot_exp_start(void); +void pot_exp_stop(void); +void sw_test(uint16_t frequency); +void lsv_experiment(int16_t start, int16_t stop, uint16_t slope, int8_t first_run); +void cv_experiment(int16_t v1, int16_t v2, int16_t start, uint8_t scans, uint16_t slope); +void chronoamp(uint16_t steps, uint16_t step_dac[], uint16_t step_seconds[]); +void swv_experiment(int16_t start, int16_t stop, uint16_t step, uint16_t pulse_height, uint16_t frequency); +void eis_waveform(int16_t offset, int16_t amplitude, uint32_t freq, uint16_t cycles); + + +#define MENU_LSV 1 +#define MENU_CV 2 +#define MENU_SWV 3 +#define MENU_AMP 4 +#define MENU_EIS 5 +#define MENU_OPS 0 + +// #define POT_GAIN_30k 0 +// #define POT_GAIN_300k 1 +// #define POT_GAIN_3M 2 +// #define POT_GAIN_500M 3 +// #define POT_LP_OFF 0 +// #define POT_LP_ON 1 + +#define ADS_F_2_5 0 +#define ADS_F_5 1 +#define ADS_F_10 2 +#define ADS_F_15 3 +#define ADS_F_25 4 +#define ADS_F_30 5 +#define ADS_F_50 6 +#define ADS_F_60 7 +#define ADS_F_100 8 +#define ADS_F_500 9 +#define ADS_F_1000 10 +#define ADS_F_2000 11 +#define ADS_F_3750 12 +#define ADS_F_7500 13 +#define ADS_F_15000 14 +#define ADS_F_30000 15 + +#define SIN_IMP_CYCLEPTS 50 diff --git a/DSTAT-temp/src/main1.c b/DSTAT-temp/src/main1.c new file mode 100644 index 0000000..c7083e6 --- /dev/null +++ b/DSTAT-temp/src/main1.c @@ -0,0 +1,1375 @@ +/** + * \file + * + * \brief Empty user application template + * + */ + +/* + * Include header files for all drivers that have been imported from + * Atmel Software Framework (ASF). + */ + +#include +#include "main.h" +#include +#include +#include +#include "ads1255.h" +#include "max5443.h" + +//volatile uint8_t gain = POT_GAIN_30k; +volatile int32_t voltage = 0; +volatile uint16_t dacindex = 0; +uint16_t dacindex_stop = 0; +volatile int8_t up = 1; +volatile uint16_t iter = 0; +uint16_t* eis_ptr = 0; +volatile uint16_t cycles = 0; +volatile uint16_t samples = 0; +volatile uint16_t tcf0period = 0; +uint32_t skip_samples = 0; + +uint8_t ads_buff = ADS_BUFF_ON; +uint8_t ads_datarate = ADS_DR_60; +uint8_t ads_pga = ADS_PGA_2; + +int16_t eis_data[500]; + +////////////////////////////////////////////////////////////////////////// +//interrupt callback setup +typedef void (*port_callback_t) (void); + +static port_callback_t portd_int0_callback; +static port_callback_t portd_int1_callback; + +static void tcf0_ovf_callback(void); +static void tcf0_ovf_callback_eis(void); +static void tce0_ovf_callback_eis(void); +static void tcd0_ovf_callback_eis(void); +static void porte_int0_lsv(void); +static void tce1_ovf_callback_lsv(void); +static void lsv_cca_callback(void); +static void porte_int0_ca(void); +static void ca_cca_callback(void); + +////////////////////////////////////////////////////////////////////////// + +enum potgain_t {POT_GAIN_100, POT_GAIN_300, POT_GAIN_3k, POT_GAIN_30k, POT_GAIN_300k, POT_GAIN_3M, POT_GAIN_30M, POT_GAIN_500M}; + +void pot_set_gain(/*uint8_t*/ potgain_t gain); + +potgain_t gain = POT_GAIN_3k; + +int8_t autogainswitch(void){ + extern int8_t over_under[ADS_OVER_UNDER_SAMPLES]; + int8_t overcurrent = 0; + static uint8_t hysteresis = 0; + static uint8_t last_return = 0; + + if (last_return==1) + { + last_return=0; + return 1; + } + + if (gain == POT_GAIN_500M) + return 0; + + if (hysteresis < ADS_OVER_UNDER_SAMPLES-1){ + ++hysteresis; + return 0; + } + + + for (uint16_t i = 0; i < ADS_OVER_UNDER_SAMPLES; ++i) + { + overcurrent += over_under[i]; + } + /*printf("OC: %i\n\r", overcurrent);*/ + + if (overcurrent == ADS_OVER_UNDER_SAMPLES && gain > POT_GAIN_300) + { + pot_set_gain(--gain); + last_return=1; + hysteresis = 0; + for (uint16_t i = 0; i < ADS_OVER_UNDER_SAMPLES; ++i) + over_under[i]=0; + + return 1; + } + + if ((overcurrent*-1) == (ADS_OVER_UNDER_SAMPLES) && gain < POT_GAIN_30M) + { + if (hysteresis < ADS_OVER_UNDER_SAMPLES+3){ + ++hysteresis; + return 0; + + } + pot_set_gain(++gain); + last_return=1; + hysteresis = 0; + for (uint16_t i = 0; i < ADS_OVER_UNDER_SAMPLES; ++i) + over_under[i]=0; + + return 1; + } + + hysteresis = 0; + return 0; +} + +void pot_set_gain(/*uint8_t*/ potgain_t gain){ + switch (gain){ + case POT_GAIN_500M: + ioport_configure_port_pin(&PORTB, PIN6_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); //A + ioport_configure_port_pin(&PORTB, PIN7_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); //B + ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); //C + printf("INFO: 500M\n\r"); + break; + case POT_GAIN_30M: + ioport_configure_port_pin(&PORTB, PIN6_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN7_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + printf("INFO: 30M\n\r"); + break; + case POT_GAIN_3M: + ioport_configure_port_pin(&PORTB, PIN6_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + printf("INFO: 3M\n\r"); + break; + case POT_GAIN_300k: + ioport_configure_port_pin(&PORTB, PIN6_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + printf("INFO: 300k\n\r"); + break; + case POT_GAIN_30k: + ioport_configure_port_pin(&PORTB, PIN6_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN7_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + printf("INFO: 30k\n\r"); + break; + case POT_GAIN_3k: + ioport_configure_port_pin(&PORTB, PIN6_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN7_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + printf("INFO: 3k\n\r"); + break; + case POT_GAIN_300: + ioport_configure_port_pin(&PORTB, PIN6_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + printf("INFO: 300\n\r"); + break; + case POT_GAIN_100: + ioport_configure_port_pin(&PORTB, PIN6_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTD, PIN4_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + printf("INFO: 100\n\r"); + break; + + default: + printf("WAR: Invalid pot gain.\n\r"); + break; + + return; + } +} + +inline void pot_exp_start(void){ + ioport_configure_port_pin(&PORTB, PIN4_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN3_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); +} + +inline void pot_exp_stop(void){ + ioport_configure_port_pin(&PORTB, PIN4_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN5_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTB, PIN3_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); +} + +void cv_experiment(int16_t v1, int16_t v2, int16_t start, uint8_t scans, uint16_t slope){ + // check if start is [v1,v2] + int8_t firstrun = 1; + + if((start < v1 && start < v2) || (start > v1 && start > v2)) + { + printf("ERR: Start must be within [v1, v2]\n\r"); + return; + } + + RTC.CTRL = RTC_PRESCALER_OFF_gc; + while (RTC.STATUS & RTC_SYNCBUSY_bm); + RTC.CNT = 0; + RTC.PER = 0xffff; + RTC.CTRL = RTC_PRESCALER_DIV1024_gc; // 1 s tick + + + while(scans > 0){ + if (start != v1){ + lsv_experiment(start,v1,slope,firstrun); + firstrun = 0; + } + if (start == v2 && scans == 1) + firstrun = -1; + lsv_experiment(v1,v2,slope, firstrun); + if (scans == 1) + firstrun = -1; + if (start != v2) + lsv_experiment(v2,start,slope, firstrun); + scans--; + firstrun = 0; + } + + printf("Time: %lu s \n\r", rtc_get_time()); + + return; +} + +void lsv_experiment(int16_t start, int16_t stop, uint16_t slope, int8_t first_run){ + //check experiment limits + if(start<-1500 || start>1500 ||start==stop|| stop<-1500 || stop>1500 || slope>7000) + { + printf("ERR: Experiment parameters outside limits\n\r"); + return; + } + + uint16_t dacindex_start = ceil(start*(65535/(double)3000)+32767); + dacindex_stop = ceil(stop*(65535/(double)3000)+32767); +// uint16_t period; + uint32_t timer_period; + uint16_t temp_div; + + + printf("Firstrun:%i\n\r", first_run); + + max5443_set_voltage1(dacindex_start); + + if (first_run == 1 || first_run == 2){ + + pot_exp_start(); + ads1255_rdatac(); + tc_enable(&TCC1); + + ads1255_sync(); + +// voltage = TCE1.CNT; + tc_enable(&TCC0); + tc_set_overflow_interrupt_callback(&TCC0, tcf0_ovf_callback); + tc_set_overflow_interrupt_callback(&TCC1, tce1_ovf_callback_lsv); + tc_set_cca_interrupt_callback(&TCC1, lsv_cca_callback); + portd_int0_callback = porte_int0_lsv; + + //set EVCH0 event + EVSYS.CH0MUX = EVSYS_CHMUX_TCC0_OVF_gc; + EVSYS.CH0CTRL = 0; + + timer_period = ceil(1/((double)slope/(3000./65535))*(F_CPU)); + temp_div = ceil(timer_period/65535.); + + if (temp_div <= 1){ + tc_write_clock_source(&TCC0,TC_CLKSEL_DIV1_gc); + } + else if (temp_div == 2){ + tc_write_clock_source(&TCC0,TC_CLKSEL_DIV2_gc); + timer_period /= 2; + } + else if (temp_div <= 4){ + tc_write_clock_source(&TCC0,TC_CLKSEL_DIV4_gc); + timer_period /= 4; + } + else if (temp_div <= 8){ + tc_write_clock_source(&TCC0,TC_CLKSEL_DIV8_gc); + timer_period /= 8; + } + else if (temp_div <= 64){ + tc_write_clock_source(&TCC0,TC_CLKSEL_DIV64_gc); + timer_period /= 64; + } + else if (temp_div <= 256){ + tc_write_clock_source(&TCC0,TC_CLKSEL_DIV256_gc); + timer_period /= 256; + } + else if (temp_div <= 1024){ + tc_write_clock_source(&TCC0,TC_CLKSEL_DIV1024_gc); + timer_period /= 1024; + } + else{ + printf("ERR: Frequency/ADC rate is too low\n\r"); + return; + } + + printf("Period:%lu\n\r", timer_period); + ads1255_wakeup(); + tc_write_period(&TCC1, 0xffff); + tc_write_period(&TCC0, (uint16_t)timer_period); + } + + TCC1.CNT = dacindex_start; + + if (stop > start) + { + up = 1; + tc_set_direction(&TCC1, TC_UP); + } + else + { + up = -1; + tc_set_direction(&TCC1, TC_DOWN); + } + + tc_write_cc(&TCC1, TC_CCA, dacindex_stop); + tc_enable_cc_channels(&TCC1, TC_CCAEN); + TCC0.CNT = 0; + + tc_set_cca_interrupt_level(&TCC1, TC_INT_LVL_HI); + tc_set_overflow_interrupt_level(&TCC0, TC_OVFINTLVL_MED_gc); +// PORTE.INTCTRL = PORT_INT0LVL_LO_gc; + PORTD.INTCTRL = PORT_INT0LVL_LO_gc; + + tc_write_clock_source(&TCC1, TC_CLKSEL_EVCH0_gc); + + + while (up != 0) + { + } + + if (first_run == -1 || first_run == 2) + { + tc_disable(&TCC0); + TCC0.CNT = 0x0; + tc_disable(&TCC1); + pot_exp_stop(); + ads1255_standby(); + } + + return; +} + +static void porte_int0_lsv(void){ + if (autogainswitch()==0){ +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + if (gain == POT_GAIN_300) + printf("%u, %ld00000\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_3k) + printf("%u, %ld0000\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_30k) + printf("%u, %ld000\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_300k) + printf("%u, %ld00\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_3M) + printf("%u, %ld0\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_30M) + printf("%u, %ld\n\r", TCC1.CNT, ads1255_read()); + else + printf("%u, %lu\n\r", TCC1.CNT, ads1255_read()); + } + else{ +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + ads1255_read(); + } +} + +static void tcf0_ovf_callback(void){ + max5443_set_voltage1(TCC1.CNT); +} + +static void tce1_ovf_callback_lsv(void){ +// printf("TCE1_OVF\n\r"); +// PORTE.INTCTRL = PORT_INT0LVL_OFF_gc; + PORTD.INTCTRL = PORT_INT0LVL_OFF_gc; + tc_set_overflow_interrupt_level(&TCC0, TC_OVFINTLVL_OFF_gc); + tc_set_overflow_interrupt_level(&TCC1, TC_OVFINTLVL_OFF_gc); + up = 0; + return; +} + +static void lsv_cca_callback(void) + { +// printf("CCA\n\r"); +// PORTE.INTCTRL = PORT_INT0LVL_OFF_gc; + PORTD.INTCTRL = PORT_INT0LVL_OFF_gc; + tc_set_overflow_interrupt_level(&TCC0, TC_OVFINTLVL_OFF_gc); + tc_set_cca_interrupt_level(&TCC1, TC_INT_LVL_OFF); + up = 0; + return; + } + + +void chronoamp(uint16_t steps, uint16_t step_dac[], uint16_t step_seconds[]){ + + while (RTC.STATUS & RTC_SYNCBUSY_bm); + RTC.PER = 999; + while (RTC.STATUS & RTC_SYNCBUSY_bm); + RTC.CTRL = RTC_PRESCALER_DIV1_gc; + + EVSYS.CH0MUX = EVSYS_CHMUX_RTC_OVF_gc; + + portd_int0_callback = porte_int0_ca; + + tc_enable(&TCC0); + tc_set_cca_interrupt_callback(&TCC0, ca_cca_callback); + + ads1255_rdatac(); + ads1255_wakeup(); + + tc_write_period(&TCC0,0xffff); + tc_write_clock_source(&TCC0, TC_CLKSEL_EVCH0_gc); + tc_set_direction(&TCC0, TC_UP); + tc_enable_cc_channels(&TCC0, TC_CCAEN); + tc_set_cca_interrupt_level(&TCC0, TC_INT_LVL_HI); + TCC0.CNT = 0; + + pot_exp_start(); + + for (uint8_t i = 0; i < steps; ++i) + { + up = 1; + tc_write_cc(&TCC0, TC_CCA, TCC0.CNT+step_seconds[i]-1); + RTC.CNT=0; + max5443_set_voltage1(step_dac[i]); + //PORTE.INTCTRL = PORT_INT0LVL_LO_gc; + PORTD.INTCTRL = PORT_INT0LVL_LO_gc; + while (up !=0); + } + + tc_set_cca_interrupt_level(&TCC0, TC_INT_LVL_OFF); + tc_write_clock_source(&TCC0, TC_CLKSEL_OFF_gc); + tc_disable(&TCC0); + pot_exp_stop(); + ads1255_standby(); + + return; +} + +static void porte_int0_ca(void){ + if (autogainswitch()==0){ + //while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + if (gain == POT_GAIN_300) + printf("%u, %ld00000\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_3k) + printf("%u, %ld0000\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_30k) + printf("%u, %ld000\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_300k) + printf("%u, %ld00\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_3M) + printf("%u, %ld0\n\r", TCC1.CNT, ads1255_read()); + else if (gain == POT_GAIN_30M) + printf("%u, %ld\n\r", TCC1.CNT, ads1255_read()); + else + printf("%u, %lu\n\r", TCC1.CNT, ads1255_read()); + } + else{ + //while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + ads1255_read(); + } +} + +static void ca_cca_callback(void) + { + //PORTE.INTCTRL = PORT_INT0LVL_OFF_gc; + PORTD.INTCTRL = PORT_INT0LVL_OFF_gc; + up = 0; + return; + } + +void swv_experiment(int16_t start, int16_t stop, uint16_t step, uint16_t pulse_height, uint16_t frequency){ + //check experiment limits +// if((start-pulse_height)<-1500 || (start+pulse_height)>(1500)|| start == stop || stop<-1500 || (stop+pulse_height)>1500 || step<1 || step>1500 || pulse_height > 1500 || pulse_height < 1) +// { +// printf("ERR: Experiment parameters outside limits\n\r"); +// //return; +// } + + int32_t forward = 0; + int32_t reverse = 0; + int32_t data_buffer; + uint8_t direction; + uint16_t dacindex_start = ceil((start)*(65535/(double)3000))+32767; + uint16_t dacindex_stop = ceil(stop*(65535/(double)3000))+32767; + uint16_t dacindex_step = ceil(step*(65535/(double)3000)); + uint16_t dacindex_pulse_height = ceil(pulse_height*(65535/(double)3000)); + uint16_t dacindex = dacindex_start; + uint32_t period; + int16_t fgain = -1; + int16_t rgain = -1; + + + if (start < stop) + direction = 1; + else + direction = 0; + + tc_enable(&TCF0); + + frequency *= 2; //compensate for half-period triggers + + //calculate time to ADC trigger + period = ceil((1/(double)frequency)*F_CPU); + uint8_t temp_div = ceil((double)period/UINT16_MAX); + + if (temp_div == 1) + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV1_gc); + else if (temp_div == 2){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV2_gc); + period /= 2; + } + else if (temp_div <= 4){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV4_gc); + period /= 4; + } + else if (temp_div <= 8){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV8_gc); + period /= 8; + } + else if (temp_div <= 64){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV64_gc); + period /= 64; + } + else if (temp_div <= 256){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV256_gc); + period /= 256; + } + else if (temp_div <= 1024){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV1024_gc); + period /= 1024; + } + else{ + printf("Frequency/ADC rate is too low\n\r"); + return; + } + + tc_write_period(&TCF0, (uint16_t)period); + + if (direction == 1) + max5443_set_voltage1(dacindex+dacindex_pulse_height); + else + max5443_set_voltage1(dacindex-dacindex_pulse_height); + + ads1255_wakeup(); + ads1255_rdatac(); + ads1255_sync(); + + pot_exp_start(); + TCF0.CNT = 0; + while (!tc_is_overflow(&TCF0)); + ads1255_wakeup(); + TCF0.CNT = 0; + + while ((dacindex <= dacindex_stop && direction == 1) || (dacindex >= dacindex_stop && direction == 0)){ + tc_clear_overflow(&TCF0); + + if (fgain > -1) + //printf("%u, %li, %li\n\r", dacindex, forward*fgain, reverse*rgain); + printf("%u, %li%0*lu, %li%0*lu\n\r", dacindex, fgain, 0, forward, rgain, 0, reverse); + + forward = 0; + reverse = 0; + + while (!tc_is_overflow(&TCF0)){ + autogainswitch(); + if (gain <= POT_GAIN_30M) + fgain = 0; + else + fgain = gain-1; + + + while (ioport_pin_is_low(IOPORT_CREATE_PIN(PORTD, 5))); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + +// while (ioport_pin_is_low(IOPORT_CREATE_PIN(PORTE, 3))); +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// forward = ads1255_read_fast24(); + forward = ads1255_read(); + } + + + if (direction == 1) + max5443_set_voltage1(dacindex-dacindex_pulse_height); + else + max5443_set_voltage1(dacindex+dacindex_pulse_height); + + + tc_clear_overflow(&TCF0); + if (direction == 1) + dacindex += dacindex_step; + else + dacindex -= dacindex_step; + + while (!tc_is_overflow(&TCF0)){ + autogainswitch(); + if (gain <= POT_GAIN_30M) + rgain = 0; + else + rgain = gain-1; + + while (ioport_pin_is_low(IOPORT_CREATE_PIN(PORTD, 5))); + while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5))); + +// while (ioport_pin_is_low(IOPORT_CREATE_PIN(PORTE, 3))); +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// reverse = ads1255_read_fast24(); + reverse = ads1255_read(); + } + + if (direction == 1) + max5443_set_voltage1(dacindex+dacindex_pulse_height); + else + max5443_set_voltage1(dacindex-dacindex_pulse_height); + + } + + pot_exp_stop(); + tc_write_clock_source(&TCF0, TC_CLKSEL_OFF_gc); + tc_disable(&TCF0); + tc_write_count(&TCF0,0); + ads1255_standby(); + + return; +} + +void eis_waveform(int16_t offset, int16_t amplitude, uint32_t freq, uint16_t cycle){ + + cycles = cycle; + uint16_t dacindex = ceil(offset*(65535/(double)3000)+32767); + + max5443_set_voltage1(dacindex); + + tc_enable(&TCF0); + tc_set_overflow_interrupt_callback(&TCF0, tcf0_ovf_callback_eis); + tc_enable(&TCE1); + tc_enable(&TCE0); + tc_enable(&TCD0); + + tc_set_overflow_interrupt_callback(&TCE0, tce0_ovf_callback_eis); + tc_set_overflow_interrupt_callback(&TCD0, tcd0_ovf_callback_eis); + + if (freq > 10000) + { + skip_samples = 300000UL/freq; + } + + ////// + + for (int i = 0; i<500; i++) + eis_data[i]=0; + + ////// + +// if (freq > 1000) +// samples=ceil(400000/freq); +// else +// samples = 500; + samples = 500; + + uint32_t timer_period; + uint8_t temp_div; + uint16_t V[samples]; + eis_ptr = (uint16_t*)&V; + up = 1; + + for (int i = 0; i < samples; i++) + { + V[i] = dacindex + floor((cos(2*M_PI*i/(samples-1))*amplitude)*(65536/(double)3000)); +// printf("%u\n\r", V[i]); + } + + pot_exp_start(); + + timer_period = round(F_CPU/((freq)/10.*(double)samples)); + printf("timer_period %lu\n\r", timer_period); + temp_div = ceil(timer_period/65535.); + printf("temp_div %u\n\r", temp_div); + EVSYS.CH0MUX = EVSYS_CHMUX_TCF0_OVF_gc; //TCF0: DAC timer, TCE1: cos iterator, TCE0: cycle counter + EVSYS.CH1MUX = EVSYS_CHMUX_TCE1_OVF_gc; +// EVSYS.CH2MUX = EVSYS_CHMUX_PORTE_PIN3_gc; + EVSYS.CH2MUX = EVSYS_CHMUX_PORTD_PIN5_gc; + + + if (temp_div <= 1){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV1_gc); + printf("DIV1_gc\n\r"); + } + else if (temp_div == 2){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV2_gc); + timer_period /= 2; + } + else if (temp_div <= 4){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV4_gc); + timer_period /= 4; + } + else if (temp_div <= 8){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV8_gc); + timer_period /= 8; + } + else if (temp_div <= 64){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV64_gc); + timer_period /= 64; + } + else if (temp_div <= 256){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV256_gc); + timer_period /= 256; + } + else if (temp_div <= 1024){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV1024_gc); + timer_period /= 1024; + } + else{ + printf("ERR: Frequency/ADC rate is too low\n\r"); + return; + } + + tcf0period = (uint16_t)timer_period; + printf("tcf0max = %lu\n\r", tcf0period*(uint32_t)samples); + + tc_write_period(&TCF0, (uint16_t)timer_period); + tc_write_period(&TCE1, samples-1); + tc_write_period(&TCE0, cycles); + tc_write_period(&TCD0, skip_samples); + + ads1255_wakeup(); + ads1255_rdatac(); + TCF0.CNT = 0; + TCE1.CNT = 0; + TCE0.CNT = 1; + TCD0.CNT = 1; + + tc_write_clock_source(&TCE1, TC_CLKSEL_EVCH0_gc); + tc_write_clock_source(&TCE0, TC_CLKSEL_EVCH1_gc); + tc_write_clock_source(&TCD0, TC_CLKSEL_EVCH2_gc); + + if (freq > 10000) + tc_set_overflow_interrupt_level(&TCD0, TC_OVFINTLVL_MED_gc); + else +// PORTE.INTCTRL = PORT_INT1LVL_MED_gc; + PORTD.INTCTRL = PORT_INT1LVL_MED_gc; + + tc_set_overflow_interrupt_level(&TCF0, TC_OVFINTLVL_LO_gc); + tc_set_overflow_interrupt_level(&TCE0, TC_OVFINTLVL_HI_gc); + + while (up != 0) + { + } + + tc_write_clock_source(&TCF0, TC_CLKSEL_OFF_gc); + tc_write_clock_source(&TCE1, TC_CLKSEL_OFF_gc); + tc_write_clock_source(&TCE0, TC_CLKSEL_OFF_gc); + tc_write_clock_source(&TCD0, TC_CLKSEL_OFF_gc); + tc_disable(&TCF0); + TCF0.CNT = 0x0; + + ads1255_standby(); + + for (uint16_t i=0; i<500; i++){ + if (eis_data[i] !=0) + printf("%i, %i\n\r", i, eis_data[i]); + } +// tc_disable(&TCE1); +// TCE1.CNT = 0x0; + return; +} + +static void tcf0_ovf_callback_eis(void){ + max5443_set_voltage1(*(eis_ptr+TCE1.CNT)); + return; +} + +static void tce0_ovf_callback_eis(void){ +// printf("TCC0_OVF\n\r"); + tc_set_overflow_interrupt_level(&TCF0, TC_OVFINTLVL_OFF_gc); + tc_set_overflow_interrupt_level(&TCD0, TC_OVFINTLVL_OFF_gc); +// PORTE.INTCTRL = PORT_INT1LVL_OFF_gc; + PORTD.INTCTRL = PORT_INT1LVL_OFF_gc; + + up = 0; + tc_set_overflow_interrupt_level(&TCE0, TC_OVFINTLVL_OFF_gc); + return; +} + +static void tcd0_ovf_callback_eis(void){ + uint16_t position = TCE1.CNT; + int16_t data_buff = ads1255_read_fast(); + + if (eis_data[position] == 0) + eis_data[position] = data_buff; + else + eis_data[position] = (eis_data[position] & data_buff)+((eis_data[position]^data_buff)>>1); + + return; +} + +void sw_test(uint16_t frequency){ + uint16_t dacindex_start = round((-1400)*(65536/(double)3000))+32768; + uint16_t dacindex_stop = round(1400*(65536/(double)3000))+32768; + uint32_t period; + + tc_enable(&TCF0); + + //calculate time to ADC trigger + period = round(((1/(double)frequency)*F_CPU)); + uint8_t temp_div = ceil(period/UINT16_MAX); + + if (temp_div == 1) + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV1_gc); + else if (temp_div == 2){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV2_gc); + period /= 2; + } + else if (temp_div <= 4){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV4_gc); + period /= 4; + } + else if (temp_div <= 8){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV8_gc); + period /= 8; + } + else if (temp_div <= 64){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV64_gc); + period /= 64; + } + else if (temp_div <= 256){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV256_gc); + period /= 256; + } + else if (temp_div <= 1024){ + tc_write_clock_source(&TCF0,TC_CLKSEL_DIV1024_gc); + period /= 1024; + } + else{ + printf("ERR: Frequency/ADC rate is too low\n\r"); + return; + } + + tc_write_period(&TCF0, (uint16_t)period/2); + pot_exp_start(); + tc_write_count(&TCF0,0); + + while (1){ + tc_clear_overflow(&TCF0); + while (!tc_is_overflow(&TCF0)); + max5443_set_voltage1(dacindex_start); + tc_clear_overflow(&TCF0); + while (!tc_is_overflow(&TCF0)); + max5443_set_voltage1(dacindex_stop); + } + pot_exp_stop(); + tc_disable(&TCF0); + tc_write_count(&TCF0,0); + return; +} + +void menu(uint8_t selection){ + int16_t start = 2000; + int16_t stop = 2000; + uint16_t slope = 0; + uint16_t height = 0; + short unsigned int scans = 0; + int16_t v1 = 2000; + int16_t v2 = 2000; + uint32_t freq = 120000; + uint16_t periods = 0; + uint16_t amp_dac[20]; + uint16_t amp_seconds[20]; + + char input = 'x'; + + switch (selection) + { + case MENU_OPS: + printf("Options:\n\r"); + + do { + printf("ADS Buffer (Y/N): "); + scanf("%c", &input); + printf("%c\n\r", input); + + if (input == 'y' || input == 'Y') + ads_buff = ADS_BUFF_ON; + else if (input == 'n' || input == 'N') + ads_buff = ADS_BUFF_OFF; + }while (!(input == 'y'||input == 'Y'||input == 'n'||input == 'N')); + + do { + printf("ADS sample rate: \n\r"); + printf("1 2.5 Hz\n\r"); + printf("2 5 Hz\n\r"); + printf("3 10 Hz\n\r"); + printf("4 15 Hz\n\r"); + printf("5 25 Hz\n\r"); + printf("6 30 Hz\n\r"); + printf("7 50 Hz\n\r"); + printf("8 60 Hz\n\r"); + printf("9 100 Hz\n\r"); + printf("10 500 Hz\n\r"); + printf("11 1 kHz\n\r"); + printf("12 2 kHz\n\r"); + printf("13 3.75 kHz\n\r"); + printf("14 7.5 kHz\n\r"); + printf("15 15 kHz\n\r"); + printf("16 30 kHz\n\r"); + + scanf("%u", &periods); + printf("%u\n\r", periods); + + if (periods == 1) + ads_datarate = ADS_DR_2_5; + else if (periods == 2) + ads_datarate = ADS_DR_5; + else if (periods == 3) + ads_datarate = ADS_DR_10; + else if (periods == 4) + ads_datarate = ADS_DR_15; + else if (periods == 5) + ads_datarate = ADS_DR_25; + else if (periods == 6) + ads_datarate = ADS_DR_30; + else if (periods == 7) + ads_datarate = ADS_DR_50; + else if (periods == 8) + ads_datarate = ADS_DR_60; + else if (periods == 9) + ads_datarate = ADS_DR_100; + else if (periods == 10) + ads_datarate = ADS_DR_500; + else if (periods == 11) + ads_datarate = ADS_DR_1000; + else if (periods == 12) + ads_datarate = ADS_DR_2000; + else if (periods == 13) + ads_datarate = ADS_DR_3750; + else if (periods == 14) + ads_datarate = ADS_DR_7500; + else if (periods == 15) + ads_datarate = ADS_DR_15000; + else if (periods == 16) + ads_datarate = ADS_DR_30000; + }while (periods == 0 || periods > 16); + + do { + printf("ADS PGA (1,2,4,8,16,32,64): \n\r"); + + scanf("%u", &periods); + printf("%u\n\r", periods); + + if (periods == 1) + ads_pga = ADS_PGA_1; + else if (periods == 2) + ads_pga = ADS_PGA_2; + else if (periods == 4) + ads_pga = ADS_PGA_4; + else if (periods == 8) + ads_pga = ADS_PGA_8; + else if (periods == 16) + ads_pga = ADS_PGA_16; + else if (periods == 32) + ads_pga = ADS_PGA_32; + else if (periods == 64) + ads_pga = ADS_PGA_64; + else + periods = 0; + }while (periods == 0 || periods > 64); + + ads1255_setup(ads_buff,ads_datarate,ads_pga); + + break; + case MENU_LSV: + printf("LSV:\n\r"); + + do { + printf("Start (-1500 - 1500 mV): "); + scanf("%d", &start); + printf("%d\n\r", start); + + if (start > 1500 && start < -1500) + { + printf("Invalid selection.\n\r"); + } + }while (start > 1500 && start < -1500); + + do { + printf("Stop (-1500 - 1500 mV): "); + scanf("%d", &stop); + printf("%d\n\r", stop); + + if (stop > 1500 && stop < -1500) + { + printf("Invalid selection.\n\r"); + } + }while (stop > 1500 && stop < -1500); + + do { + printf("Slope (1 - 7000 mV/s): "); + scanf("%u", &slope); + printf("%u\n\r", slope); + + if (slope > 7000 && slope < 1) + { + printf("Invalid selection.\n\r"); + } + }while (slope > 7000 && slope < 1); + + lsv_experiment(start,stop,slope,2); + break; + + case MENU_CV: + printf("CV:\n\r"); + + do { + printf("v1 (-1500 - 1500 mV): "); + scanf("%d", &v1); + printf("%d\n\r", v1); + + if (v1 > 1500 && v1 < -1500) + { + printf("Invalid selection.\n\r"); + } + }while (v1 > 1500 && v1 < -1500); + + do { + printf("v2 (-1500 - 1500 mV): "); + scanf("%d", &v2); + printf("%d\n\r", v2); + + if (v2 > 1500 && v2 < -1500) + { + printf("Invalid selection.\n\r"); + } + }while (v2 > 1500 && v2 < -1500); + + do { + printf("Start (-1500 - 1500 mV): "); + scanf("%d", &start); + printf("%d\n\r", start); + + if (start > 1500 && start < -1500) + { + printf("Invalid selection.\n\r"); + } + }while (start > 1500 && start < -1500); + + do { + printf("Slope (1 - 7000 mV/s): "); + scanf("%u", &slope); + printf("%u\n\r", slope); + + if (slope > 7000 && slope < 1) + { + printf("Invalid selection.\n\r"); + } + }while (slope > 7000 && slope < 1); + + do { + printf("Scans (1-255): "); + scanf("%hu", &scans); + printf("%hu\n\r", scans); + + if (scans < 1) + { + printf("Invalid selection.\n\r"); + } + }while (scans < 1); + + cv_experiment(v1,v2,start,scans,slope); + break; + case MENU_EIS: + printf("EIS:\n\r"); + + do { + printf("freq (1-100000 dHz): \n\r"); + scanf("%lu", &freq); + + if (freq > 100000 || freq == 0) + { + printf("Invalid selection.\n\r"); + } + }while (freq > 100000 || freq == 0); + + do { + printf("offset (-1500-1500 mV): \n\r"); + scanf("%d", &start); + + if (start > 1500 || start < -1500) + { + printf("Invalid selection.\n\r"); + } + }while (start > 1500 || start < -1500); + + do { + printf("amplitude (1-500 mV): \n\r"); + scanf("%u", &slope); + + if (slope > 500) + { + printf("Invalid selection.\n\r"); + } + }while (slope > 500); + + do { + printf("cycles: \n\r"); + scanf("%u", &periods); + + if (periods > 10000 || periods == 0) + { + printf("Invalid selection.\n\r"); + } + }while (periods > 10000 || periods == 0); + ads1255_setup(ADS_BUFF_ON,ADS_DR_30000,ADS_PGA_2); + eis_waveform(start, slope, freq, periods); + break; + case MENU_SWV: + printf("SWV:\n\r"); + + do { + printf("Start (-1500-1500 mV): "); + scanf("%d", &start); + printf("%d \n\r",start); + + if (start > 1500 || start < -1500) + { + printf("Invalid selection.\n\r"); + } + }while (start > 1500 || start < -1500); + + do { + printf("Stop (-1500-1500 mV): "); + scanf("%d", &stop); + printf("%d \n\r", stop); + + if (stop > 1500 || stop < -1500) + { + printf("Invalid selection.\n\r"); + } + }while (stop > 1500 || stop < -1500); + + do { + printf("Step (1-400 mV): "); + scanf("%u", &slope); + printf("%u \n\r", slope); + + if (slope > 400 || slope < 1) + { + printf("Invalid selection.\n\r"); + } + }while (slope > 400 || slope < 1); + + do { + printf("Pulse height (1-500 mV): "); + scanf("%u", &height); + printf("%u \n\r", height); + + if (height > 500) + { + printf("Invalid selection.\n\r"); + } + }while (height > 500); + + do { + printf("freq (1-10000 Hz): "); + scanf("%lu", &freq); + printf("%lu\n\r", freq); + + if (freq > 10000 || freq == 0) + { + printf("Invalid selection.\n\r"); + } + }while (freq > 10000 || freq == 0); + + do { + printf("Scans: "); + scanf("%u", &periods); + printf("%u\n\r", periods); + + if (periods == 0) + printf("Invalid selection.\n\r"); + }while (periods == 0); + + for (uint16_t i = 0; i < periods; ++i) + swv_experiment(start, stop, slope, height, freq); + break; + + case MENU_AMP: + printf("Chronoamperometry:\n\r"); + + do { + printf("Steps (1-20): "); + scanf("%u", &slope); + printf("%u\n\r", slope); + + if (slope > 20 || slope == 0) + { + printf("Invalid selection.\n\r"); + } + }while (slope > 20 || slope == 0); + + for (uint16_t i = 0; i 1500 || start < -1500) + printf("Invalid selection.\n\r"); + }while (start > 1500 || start < -1500); + + amp_dac[i] = ceil(start*(65535/(double)3000)+32767); + } + chronoamp(slope, amp_dac, amp_seconds); + + break; + default: + printf("Invalid selection.\n\r"); + return; + return; + } +} + +int main (void) +{ + board_init(); + pmic_init(); + + irq_initialize_vectors(); + cpu_irq_enable(); + sleepmgr_init(); + sysclk_init(); //Disables ALL peripheral clocks D: + rtc_init(); + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS); + + pmic_set_scheduling(PMIC_SCH_ROUND_ROBIN); + + stdio_usb_init(&USARTD1); + stdio_usb_enable(); +// printf("DStat v1 25 Jun 2012\n\r"); + + ads1255_init_pins(); + ads1255_init_module(); + ads1255_setup(ADS_BUFF_ON,ADS_DR_60,ADS_PGA_2); +// // PORTE.INT0MASK = PIN3_bm; +// // PORTE.INT1MASK = PIN3_bm; +// // PORTE.INTCTRL = PORT_INT0LVL_OFF_gc; +// // PORTE.INTCTRL = PORT_INT1LVL_OFF_gc; + PORTD.INT0MASK = PIN5_bm; + PORTD.INT1MASK = PIN5_bm; + PORTD.INTCTRL = PORT_INT0LVL_OFF_gc | PORT_INT1LVL_OFF_gc; + + pot_exp_stop(); + max5443_init_pins(); + max5443_init_module(); + delay_ms(300); + + uint16_t input; + + gain = POT_GAIN_3k; + pot_set_gain(gain); + +// RTC.CTRL = RTC_PRESCALER_OFF_gc; +// while (RTC.STATUS & RTC_SYNCBUSY_bm); +// RTC.CNT = 0; +// RTC.PER = 0xffff; +// RTC.CTRL = RTC_PRESCALER_DIV1_gc; + + ads1255_wakeup(); + ads1255_rdatac(); + int32_t data1 = 0; + +// max5443_set_voltage1(21845); //1V +// pot_exp_start(); + + while (1){ + ads1255_standby(); + + printf("Choose Experiment type:\n\r"); + printf("Options:0, LSV:1, CV:2, SWV:3, AMP:4, EIS:5\n\r"); + printf("DStat v1.1 27 Aug 2012\n\r"); + + scanf("%u", &input); + + if (input < 6) + menu(input); + else + printf("Invalid selection.\n\r"); + + getchar(); + + } + +} + + +ISR(PORTD_INT0_vect){ + if (portd_int0_callback) { + portd_int0_callback(); + } +// if (autogainswitch()==0){ +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// if (gain == POT_GAIN_30k) +// { +// printf("%u, %ld\n\r", TCC1.CNT, ads1255_read()*100); +// } +// else if (gain == POT_GAIN_300k) +// { +// printf("%u, %ld\n\r", TCC1.CNT, ads1255_read()*10); +// } +// else if (gain == POT_GAIN_3M) +// { +// printf("%u, %ld\n\r", TCC1.CNT, ads1255_read()); +// } +// else +// { +// printf("%u, %lu\n\r", TCC1.CNT, ads1255_read()); +// } +// /*printf("%li, %li\n\r", voltage, ads1255_read());*/ +// } +// else{ +// while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTE, 3))); +// ads1255_read(); +// } +} + +ISR(PORTD_INT1_vect){ +// if (autogainswitch()==0){ +// printf("INT1\n\r"); +// static uint16_t skip = 0; +// if (++skip <= skip_samples) +// return; +// skip = 0; +// +// if (samples == 500){ +// printf("%u, %d\n\r", TCE1.CNT, ads1255_read_fast()); +// return; +// } +// +// uint32_t iter1 = TCE1.CNT*(uint32_t)tcf0period + TCF0.CNT; +// +// printf("%lu, %d\n\r", iter1, ads1255_read_fast()/**(3./65535/30000.)*/); + + uint16_t position = TCE1.CNT; + int16_t data_buff = ads1255_read_fast(); + + if (eis_data[position] == 0) + eis_data[position] = data_buff; + else + eis_data[position] = (eis_data[position] & data_buff)+((eis_data[position]^data_buff)>>1); + + + return; + +} \ No newline at end of file diff --git a/DSTAT-temp/src/max5443.c b/DSTAT-temp/src/max5443.c new file mode 100644 index 0000000..c08d7b6 --- /dev/null +++ b/DSTAT-temp/src/max5443.c @@ -0,0 +1,89 @@ +/* + * max5443.c + * + * Created: 06/04/2012 7:29:47 PM + * Author: mdryden + */ + +#include +// #include +// #include +// #include + +// struct spi_device spi_device_conf_c = { +// .id = IOPORT_CREATE_PIN(PORTC, 4) +// }; + +struct usart_spi_device spi_device_conf_c = { + .id = IOPORT_CREATE_PIN(PORTC, 4) + }; + +void max5443_init_pins(void){ + ioport_configure_port_pin(&PORTC, PIN4_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTC, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); + ioport_configure_port_pin(&PORTC, PIN7_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); +// ioport_configure_port_pin(&PORTC, PIN3_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); //CLR +// delay_us(1); +// ioport_configure_port_pin(&PORTC, PIN3_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); +} + +void max5443_init_module(void){ +// spi_master_init(&SPIC); +// spi_master_setup_device(&SPIC, &spi_device_conf_c, SPI_MODE_0, 24000000UL, 0); +// spi_enable(&SPIC); + + usart_spi_init(&USARTC1); + usart_spi_setup_device(&USARTC1, &spi_device_conf_c, SPI_MODE_0, 24000000UL, 0); +// usart_spi_enable(&USARTC1); +} + +void max5443_set_voltage1(uint16_t dacindex){ +/* char logstr[10];*/ + + static union{ + uint8_t ui8[2]; + uint16_t ui16; + } buffer; + + if (buffer.ui16 == dacindex) + return; + + buffer.ui16 = dacindex; + + irqflags_t flags; + flags = cpu_irq_save(); + +// spi_select_device(&SPIC, &spi_device_conf_c); +// spi_write_single(&SPIC, buffer.ui8[1]); +// delay_cycles(40); +// spi_write_single(&SPIC, buffer.ui8[0]); +// spi_deselect_device(&SPIC, &spi_device_conf_c); + + usart_spi_select_device(&USARTC1, &spi_device_conf_c); + usart_spi_write_single(&USARTC1, buffer.ui8[1]); + delay_cycles(40); + usart_spi_write_single(&USARTC1, buffer.ui8[0]); + usart_spi_deselect_device(&USARTC1, &spi_device_conf_c); + + cpu_irq_restore(flags); + return; +} + +// void max5443_set_voltage_8bit(uint8_t dacindex){ +// spi_select_device(&SPIC, &spi_device_conf_c); +// spi_write_single(&SPIC, dacindex); +// spi_deselect_device(&SPIC, &spi_device_conf_c); +// return; +// } + +/*void max5443_set_voltage(uint8_t msb, uint8_t lsb){ + irqflags_t flags; + flags = cpu_irq_save(); + + spi_select_device(&SPIC, &spi_device_conf_c); + spi_write_single(&SPIC, msb); + spi_write_single(&SPIC, lsb); + spi_deselect_device(&SPIC, &spi_device_conf_c); + + cpu_irq_restore(flags); +}*/ \ No newline at end of file diff --git a/DSTAT-temp/src/max5443.h b/DSTAT-temp/src/max5443.h new file mode 100644 index 0000000..9f7bd99 --- /dev/null +++ b/DSTAT-temp/src/max5443.h @@ -0,0 +1,18 @@ +/* + * max5443.h + * + * Created: 06/04/2012 7:30:13 PM + * Author: mdryden + */ + + +#ifndef MAX5443_H_ +#define MAX5443_H_ +#include + +void max5443_init_pins(void); +void max5443_init_module(void); +void max5443_set_voltage1(uint16_t dacindex); +//void max5443_set_voltage_8bit(uint8_t dacindex); + +#endif /* MAX5443_H_ */ \ No newline at end of file diff --git a/DSTAT1.atsln b/DSTAT1.atsln index c6df6e2..2056043 100644 --- a/DSTAT1.atsln +++ b/DSTAT1.atsln @@ -3,11 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Atmel Studio Solution File, Format Version 11.00 Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "DSTAT1", "DSTAT1\DSTAT1.cproj", "{38800372-2811-4812-8069-46107EA45AA8}" EndProject +Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "DSTAT-temp", "DSTAT-temp\DSTAT-temp.cproj", "{511F3FE1-F6B0-4E6D-877C-322C1167607E}" +EndProject Global - GlobalSection(SubversionScc) = preSolution - Svn-Managed = True - Manager = AnkhSVN - Subversion Support for Visual Studio - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|AVR = Debug|AVR Release|AVR = Release|AVR @@ -17,8 +15,16 @@ Global {38800372-2811-4812-8069-46107EA45AA8}.Debug|AVR.Build.0 = Debug|AVR {38800372-2811-4812-8069-46107EA45AA8}.Release|AVR.ActiveCfg = Release|AVR {38800372-2811-4812-8069-46107EA45AA8}.Release|AVR.Build.0 = Release|AVR + {511F3FE1-F6B0-4E6D-877C-322C1167607E}.Debug|AVR.ActiveCfg = Debug|AVR + {511F3FE1-F6B0-4E6D-877C-322C1167607E}.Debug|AVR.Build.0 = Debug|AVR + {511F3FE1-F6B0-4E6D-877C-322C1167607E}.Release|AVR.ActiveCfg = Release|AVR + {511F3FE1-F6B0-4E6D-877C-322C1167607E}.Release|AVR.Build.0 = Release|AVR EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(SubversionScc) = preSolution + Svn-Managed = True + Manager = AnkhSVN - Subversion Support for Visual Studio + EndGlobalSection EndGlobal diff --git a/DSTAT1.atsuo b/DSTAT1.atsuo new file mode 100644 index 0000000000000000000000000000000000000000..2be864bcd1e6350ff5fa72039d02fe60e2557156 GIT binary patch literal 34304 zcmeHQ3w#vSxt|c;A_6KeA4E|^B_W%T7Y`xHCO!ZO5TfWp*z9hSmCf$DyWyb$v096* z)>o~ymr~n;Qr}uss=bO-y;`lJRch_M3WaNX>zh_-t3v<(nK{|n&FswVB<==(_vH7V zbI#1!`ObHq-}%mWCOcmlzWXN+jol+9xwE8P>ENM3Qh&|;9E1tk4U?ok2;>3>4;?zB z+>|5)|KA-(CGaKk+7Fd?0?-#=eGdQz0)v3Tz>&Zazz|?4a1?;*mqq}?fun(AfMbD? zz$joWFd7&G90wc^oCur*6awRbJm6&D3}8HP3UDeg0XPkq2%HX_3CsW{0r@}yFd1+F zYs5c{2Bds!eMVDtIF$!r5 zq)UPnH`spZ=1J|~Iw1K$pJGIG1{+9Yu_5m@Dv;Q-$9RnEW7$EvT7XcRoE`ZH`DbNTk1KdCp-~qgV z4`>EjfL6c{Tmmcy0zexO1VTU<*bE3hVhFbbE7W`JN$ky60ha?Ez}3K7;0oZIK+S=I z?`{jcU3p9Bv0W1?H}Ar&wA`kgYK*Tg@Et|oBe=SdN3T4NcyT9)xD&bcAZKlIJSL}! zB83Ofyof3NEgyXQakouciBgFmEq}QXrCJF%5EH*~Bh-xeD*25qNX_>|@aq+wd5Fnx z=d}Rkc;=zpr5jsD-8@Emw)n_Tw%&agctnLJxU|^rOuRKGd;EJ)u5I`W$)&86{|c0X z2c^JzVEG47I;#`HERQql+lFpl(pXg=`QqBO|NQ7J_UMGdK%|pJ!@wO`;eQ2cJ6~=& z0r19g+XGJ9WsY44vrT#BShMuHcgm8PHKRuaH(dJh_}d0h0I6Z?MIaC;&p8{|4^HU=cIH3IvsUR-o-}fxFU!rMM2*slXTuS=TaB3UPg&N;k^lZkAZpbpt$20}0)oDh zZ}B93|LUytf6f{X%=;zy<9N1c(Oc7_%QwuQbNBx7n{FL_8YLQ0Bf{6`tvBS~Bh9$y z%Dp$0U*Guqt@}rX$MmZiV>$od=w|twwLh+-j2zp)C}H|WX~nZq2y9U!X7nk;89BE9 z0Z70;WtBeHrhW?%Z~lw5uvNbzLrM*Kd$C% zX5U3}*Od>SIO3dj{@P({H(j)aV|gZB1KL|XB*+ltrzTuiLE>i16LO?kUQR~)V}BBL zZI+(T#{pbx(p?DoHGp2=M*ClmYYV8)gVYj33!_|XrT>vO-$`G7smUb|&u0!%64irF z81$93i!ugq)j}ECiaQbfbNx!4m{t1uNZXH76dZee6C~FbnezzNjnqAOFsE@OFn8$x zon>#8K4l8Z0Cdzvu)PzP7OZ)E#Yhc|vV%p`fch<`3W}F|R+QTpQb?P4Q3x7rIja>B06u zKo-R@1a^zGClqY|JL4JERzW1@(aCeAjrTj0M&>B+ zgd-uUKssAZace9Vo;rDQ)YIx~b4Lr>{GLcC8fuOepbbv;`d0V?p|CG9xh>k%?hkk; z7ZnzAN|I`AO-Nx1^%Env@%-YbjRHF z{&2LQ&L0fAn*u&LQnM=N3r77-{(wKWx}c6ZjpB~Scjg>9;EV8g3uB>(k9-~>j~|(4 zzaKdd_8ik1HU-OSfmDYA0iTDpN0NP6MDoBrh)dpKywFiMYS)QM?9T6(;>UKiP|5R8 z73O{)=Ah-66+^O=M}1vtHxct6b*pRxbg5IupKwhfcWC&@^r`>n+-p?=m;m~N@tzTY zRr(c3E9CEF`n598UPwV9%*xbJ8p{EsPr65^L4PXJ{tKW>O@B2cBT8h{`lfcE-&yun z`KP{EywQplR;1PQg&e2%ES-BCO}O4s+Oe`KYQY^hN+Ay#c|Xd55>Xy@1y^BbuM|6j zE@*~hcup;+Hk^mri^Y1SG0XNjpcXg^L znDC%G_Yz)Y5=m}l+-qI3R=G7<@?vHY9pdAsXcC-H_?~Q0V ztpiPJ1B})}g)0AfY4Bf(w4ZUo0+*wBwy%SwkMX8K($*a3)I$7SUgB`n7T4A|@@q@0 z3iGGblsfav%gUwgN@mGuj2Fg(8)d&@%Mv4$(9hKr=)M><)dA4bPQt-(YveFDJeax!!&2;e}j{CK%zkQ%p5oW!Oz;x z|5iuQq~R^g){6VdzSVTezhkW#jXy#c>XcihJNf5wya3}5=1u79e~QbOo|bNI}91r?jLy0_y`$qnycsNl_AoiKX{_{fgG^G{OVotl# z)PE!Ae?gnReyYT~EK_y(1`LfLgaZve1^C+6s-9ZM^Nf$8?d@B#7dufR|oQ%+Fkex z#}WH3oA$T%<&ojhE0&fySC9R4!jAs+ecqM#(zK(v)sbA1p2@Mh^P}iKjOJgi3Ak5c z!ZwUtQwSM{al^o`rE*#F^tZk7IJNc)Us`bBC= zeNWIAtw%pq;@vffzN_9!$9_tT|5oQVt;~=(uf?Bi>}LD5lmArnSJ&CLRocD&ceBsW zbKmgHx;@W4Ika&q^){lc>2J?M{;igOGCz9y2lMt{oY;7hVr+k>;oj+Lxg;D^9}02_cG z0ULoI19t#F0e%Yn4A=y`3ETm8Bj96z`D0uD8}N5v8q)FJ0fhen{1f;W@Hy}W@Fj2%kQ*w}zI0fPUs{Pv z8Qo&CZYuoY`W@@`Z5lJ+#qr^v)m*zMj~pgB+|qGOq;uQytybyjy?=SHc<(m{mR;QU zjRvV<*%IbJ)JaB7a+2VcAkM&&l_HBEHn7-?9uRksS9%=DWlQ)%5 z-+t5XU+2E_$c}xZa!vWq=J`X)5%KePwAG;wi4uuRw%k!-tk-cLUorf>MSX(bDJ$6c zZ1M6x4K?Kp2`srsv)F&Ny)pUxCAEl6CD98PCWzd}iv;!66H z@T?TD%Kr;UOPPbtjDC@Y^{=+yC~q~s{uYl#`RkgP+p)-3P0UwB@}seU%OCUv+Pywk z(6!RG&B+f9~74HUzBZ^XZX2Nrm~0BD5aH|+CutlJm#AhDRorEB3n&o&LM z^}IM*pkqScjXLQpG39JV*d2*Qbtq)!ltgQnw$S|p4PD>ay((9avNVO<5pUEbdphMM zADReaE=zUtT=_cE-5Jt?r=zLotgP(qa^ED3y%c3nX9OxIlUjSBQHt-9DreS}ZxG#? zp_1#~w`nz>2XGhkrPB*N}sKz@2vGV0HB(7fa`5Loeh%Zin#ctPgIlnE&EG zI{tiC@h6c9ulEekoy;SUDg8q_^&i(nQK}m{bLX@#>z*!}`K#;BK6w4?-91|dy^;S! zS>nb!D_0H;&;5M=>@SX6|Ksx>HrFX?>(?y2wtL&}cD66$!g8zhc6jHhH}7-=UoIY9 z@$A5&)1lE%uTz`rAI$f^Cxa+cSsg)MMOvYMFsEOH)Tx~v{m&bC9rv5)%;}r&e-`3B zQvj>{=c1OlXG3RBpKng>?C{?J`uD4^wEf8kt=aQY?Q&m4o zM2BV%d~w0Ul1WfjE$dN6gpMcv;fSv4i=O#XL03-fD3Ri8BW;zZQi|A7BE=~ft_R{v z15L%7EYLb0>t&L&<@L<-y(QzF+C!mlRaKy!O8~PfuzNJr(jwXDY~dPw^?4dPb9yTZ z<2M$-(o}r0$Lfj689kl{dnY#sBOjH}vG7D4zm!@HE9w^9+7mfWSAS`?H>-Tz zJyTl3#M~#_7boi16TfV#d`0Y<47H2Ie6lsgzd*^Ewm*<5J9F!8G`<#OUtrDibYEkq zeF6`!^Z^zEeF1)3r$0a&qJi)S0fT`ffFZzGnQVA`YM9|If*}yr#xxjhAY+w#B7dRi72h;)c zfdv5HUk`tg8omJjg=+XB_!k2%HNF&nBd|=3H^KL)VITZvHQWl{4_uuV;BZm)tYO7@DTzYE0% z8|$t_iiw5-srK&eeVvY9MO1c+bnF}IyOnkALaRNB?fS-O*sodih)Q>MiwZN3O`|Tw zevys0re3#ueF67smweUXKuY5ylgjrHtu8yB>Lu%^#JYr@#3}Yq-=gu#Pf=3jqqu%dre{@W|h4tu2gKEHUzarf=LY}cC;N^WU+{2_CltG0Sy>vjC6GuK2d z*dLW>+3gah{Shssn2N2XO9Gu6i_y8?RqvbIKk;N;YG=p(X$k1_Y&@MgeeF_M`Hl7p z`uMJ~@;ynb{JTN_Vf7{E^n3pNqgO*;$WB83V2`-}hV3K!?t5TY>yGG_#r>=QekAgm zY9zQWtL;B=7q(T(dGq~X#o(K^zq!UY6C;u;&R5@2Fpf}~;&i?_tx0~f}-u_I_ zzv64&%Kurn+WuS6{$8`#{)@kY^RLT6|6a@V&Fx>=Ln(n+<)8mdW`||^99>d7jz8KK zo;qdxNkqecPgup6%evybfUeC0KH0Wm$w&7u`DD|Erj4)Ng-mI4Z?y#Dyj;`G_TL@; zh5SSr)UF|RZ#+Mt*awlTdv7fCUV7eyd-5aOUfJ;0x-wdjb+5kSHK&AnNBw!EtKRIt be`xuk5Bpqt-o864>JIhnDT!pRdr$n|L&yp& literal 0 HcmV?d00001 diff --git a/DSTAT1/DSTAT1.cproj b/DSTAT1/DSTAT1.cproj index aab98d8..46a934c 100644 --- a/DSTAT1/DSTAT1.cproj +++ b/DSTAT1/DSTAT1.cproj @@ -7,7 +7,7 @@ $(MSBuildProjectName) $(MSBuildProjectName) $(MSBuildProjectName) - 3.0.1 + 2.11.1 @@ -192,132 +192,132 @@ True - - - BOARD=USER_BOARD - - - - - ../src - ../src/asf/common/applications/user_application/user_board - ../src/asf/common/boards - ../src/asf/common/boards/user_board - ../src/asf/common/utils - ../src/asf/xmega/utils - ../src/asf/xmega/utils/preprocessor - ../src/config - ../src/asf/common/services/usb/class/cdc/device - ../src/asf/xmega/drivers/cpu - ../src/asf/xmega/drivers/ioport - ../src/asf/xmega/drivers/nvm - ../src/asf/xmega/drivers/sleep - ../src/asf/common/services/clock - ../src/asf/common/services/delay - ../src/asf/common/services/sleepmgr - ../src/asf/common/services/usb - ../src/asf/common/services/usb/class/cdc - ../src/asf/common/services/usb/udc - ../src/asf/xmega/drivers/usb - ../src/asf/common/utils/stdio/stdio_usb - ../src/asf/xmega/drivers/spi - ../src/asf/common/services/spi/xmega_spi - ../src/asf/common/services/spi - ../src/asf/xmega/drivers/pmic - ../src/asf/xmega/drivers/tc - ../src/asf/xmega/drivers/rtc - ../src/asf/xmega/drivers/usart - - - Optimize more (-O2) - -fdata-sections - True - True - -Werror-implicit-function-declaration -Wmissing-prototypes -Wpointer-arith -Wstrict-prototypes -mrelax -std=gnu99 - - - BOARD=USER_BOARD - - - - - ../src - ../src/asf/common/applications/user_application/user_board - ../src/asf/common/boards - ../src/asf/common/boards/user_board - ../src/asf/common/utils - ../src/asf/xmega/utils - ../src/asf/xmega/utils/preprocessor - ../src/config - ../src/asf/common/services/usb/class/cdc/device - ../src/asf/xmega/drivers/cpu - ../src/asf/xmega/drivers/ioport - ../src/asf/xmega/drivers/nvm - ../src/asf/xmega/drivers/sleep - ../src/asf/common/services/clock - ../src/asf/common/services/delay - ../src/asf/common/services/sleepmgr - ../src/asf/common/services/usb - ../src/asf/common/services/usb/class/cdc - ../src/asf/common/services/usb/udc - ../src/asf/xmega/drivers/usb - ../src/asf/common/utils/stdio/stdio_usb - ../src/asf/xmega/drivers/spi - ../src/asf/common/services/spi/xmega_spi - ../src/asf/common/services/spi - ../src/asf/xmega/drivers/pmic - ../src/asf/xmega/drivers/tc - ../src/asf/xmega/drivers/rtc - ../src/avr-stl/include - ../src/asf/xmega/drivers/usart - - - Optimize more (-O2) - True - - - libprintf_flt.a - libm.a - libc.a - - - True - True - -Wl,-u,vfprintf -lm - - - ../src - ../src/asf/common/applications/user_application/user_board - ../src/asf/common/boards - ../src/asf/common/boards/user_board - ../src/asf/common/utils - ../src/asf/xmega/utils - ../src/asf/xmega/utils/preprocessor - ../src/config - ../src/asf/common/services/usb/class/cdc/device - ../src/asf/xmega/drivers/cpu - ../src/asf/xmega/drivers/ioport - ../src/asf/xmega/drivers/nvm - ../src/asf/xmega/drivers/sleep - ../src/asf/common/services/clock - ../src/asf/common/services/delay - ../src/asf/common/services/sleepmgr - ../src/asf/common/services/usb - ../src/asf/common/services/usb/class/cdc - ../src/asf/common/services/usb/udc - ../src/asf/xmega/drivers/usb - ../src/asf/common/utils/stdio/stdio_usb - ../src/asf/xmega/drivers/spi - ../src/asf/common/services/spi/xmega_spi - ../src/asf/common/services/spi - ../src/asf/xmega/drivers/pmic - ../src/asf/xmega/drivers/tc - ../src/asf/xmega/drivers/rtc - ../src/avr-stl/include - ../src/asf/xmega/drivers/usart - - - + + + BOARD=USER_BOARD + + + + + ../src + ../src/asf/common/applications/user_application/user_board + ../src/asf/common/boards + ../src/asf/common/boards/user_board + ../src/asf/common/utils + ../src/asf/xmega/utils + ../src/asf/xmega/utils/preprocessor + ../src/config + ../src/asf/common/services/usb/class/cdc/device + ../src/asf/xmega/drivers/cpu + ../src/asf/xmega/drivers/ioport + ../src/asf/xmega/drivers/nvm + ../src/asf/xmega/drivers/sleep + ../src/asf/common/services/clock + ../src/asf/common/services/delay + ../src/asf/common/services/sleepmgr + ../src/asf/common/services/usb + ../src/asf/common/services/usb/class/cdc + ../src/asf/common/services/usb/udc + ../src/asf/xmega/drivers/usb + ../src/asf/common/utils/stdio/stdio_usb + ../src/asf/xmega/drivers/spi + ../src/asf/common/services/spi/xmega_spi + ../src/asf/common/services/spi + ../src/asf/xmega/drivers/pmic + ../src/asf/xmega/drivers/tc + ../src/asf/xmega/drivers/rtc + ../src/asf/xmega/drivers/usart + + + Optimize more (-O2) + -fdata-sections + True + True + -Werror-implicit-function-declaration -Wmissing-prototypes -Wpointer-arith -Wstrict-prototypes -mrelax -std=gnu99 + + + BOARD=USER_BOARD + + + + + ../src + ../src/asf/common/applications/user_application/user_board + ../src/asf/common/boards + ../src/asf/common/boards/user_board + ../src/asf/common/utils + ../src/asf/xmega/utils + ../src/asf/xmega/utils/preprocessor + ../src/config + ../src/asf/common/services/usb/class/cdc/device + ../src/asf/xmega/drivers/cpu + ../src/asf/xmega/drivers/ioport + ../src/asf/xmega/drivers/nvm + ../src/asf/xmega/drivers/sleep + ../src/asf/common/services/clock + ../src/asf/common/services/delay + ../src/asf/common/services/sleepmgr + ../src/asf/common/services/usb + ../src/asf/common/services/usb/class/cdc + ../src/asf/common/services/usb/udc + ../src/asf/xmega/drivers/usb + ../src/asf/common/utils/stdio/stdio_usb + ../src/asf/xmega/drivers/spi + ../src/asf/common/services/spi/xmega_spi + ../src/asf/common/services/spi + ../src/asf/xmega/drivers/pmic + ../src/asf/xmega/drivers/tc + ../src/asf/xmega/drivers/rtc + ../src/avr-stl/include + ../src/asf/xmega/drivers/usart + + + Optimize more (-O2) + True + + + libprintf_flt.a + libm.a + libc.a + + + True + True + -Wl,-u,vfprintf -lm + + + ../src + ../src/asf/common/applications/user_application/user_board + ../src/asf/common/boards + ../src/asf/common/boards/user_board + ../src/asf/common/utils + ../src/asf/xmega/utils + ../src/asf/xmega/utils/preprocessor + ../src/config + ../src/asf/common/services/usb/class/cdc/device + ../src/asf/xmega/drivers/cpu + ../src/asf/xmega/drivers/ioport + ../src/asf/xmega/drivers/nvm + ../src/asf/xmega/drivers/sleep + ../src/asf/common/services/clock + ../src/asf/common/services/delay + ../src/asf/common/services/sleepmgr + ../src/asf/common/services/usb + ../src/asf/common/services/usb/class/cdc + ../src/asf/common/services/usb/udc + ../src/asf/xmega/drivers/usb + ../src/asf/common/utils/stdio/stdio_usb + ../src/asf/xmega/drivers/spi + ../src/asf/common/services/spi/xmega_spi + ../src/asf/common/services/spi + ../src/asf/xmega/drivers/pmic + ../src/asf/xmega/drivers/tc + ../src/asf/xmega/drivers/rtc + ../src/avr-stl/include + ../src/asf/xmega/drivers/usart + + + diff --git a/DSTAT1/src/asf/common/services/hugemem/avr8/avr8_hugemem.c b/DSTAT1/src/asf/common/services/hugemem/avr8/avr8_hugemem.c new file mode 100644 index 0000000..44bb9c1 --- /dev/null +++ b/DSTAT1/src/asf/common/services/hugemem/avr8/avr8_hugemem.c @@ -0,0 +1,195 @@ +/** + * \file + * + * \brief Access to huge data memory with 8-bit AVR + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include "hugemem.h" +#include "compiler.h" +#include "conf_board.h" + +#if defined(CONFIG_HAVE_HUGEMEM) || defined(__DOXYGEN__) +# if defined(__GNUC__) || defined(__DOXYGEN__) +uint_fast16_t hugemem_read16(const hugemem_ptr_t from) +{ + uint16_t value; + + asm( + "movw r30, %A1 \n\t" + "out %2, %C1 \n\t" + "ld %A0, Z+ \n\t" + "ld %B0, Z \n\t" + "out %2, __zero_reg__ \n\t" + : "=r"(value) + : "r"(from), "i"(&RAMPZ) + : "r30", "r31" + ); + + return value; +} + +uint_fast32_t hugemem_read32(const hugemem_ptr_t from) +{ + uint32_t value; + + asm( + "movw r30, %A1 \n\t" + "out %2, %C1 \n\t" + "ld %A0, Z+ \n\t" + "ld %B0, Z+ \n\t" + "ld %C0, Z+ \n\t" + "ld %D0, Z \n\t" + "out %2, __zero_reg__ \n\t" + : "=r"(value) + : "r"(from), "i"(&RAMPZ) + : "r30", "r31" + ); + + return value; +} + +void hugemem_read_block(void *to, const hugemem_ptr_t from, size_t size) +{ + // Ensure that the address range to copy to is within 64 kB boundary. + Assert(((uint32_t)to + size) <= 0x10000); + + if (size > 0) { + asm volatile( + "movw r30, %A2 \n\t" + "out %3, %C2 \n\t" + "get_%=: \n\t" + "ld __tmp_reg__, Z+ \n\t" + "st X+, __tmp_reg__ \n\t" + "sbiw %A1, 1 \n\t" + "brne get_%= \n\t" + "out %3, __zero_reg__ \n\t" + : "+x"(to), "+w"(size) + : "r"(from), "i"(&RAMPZ) + : "r30", "r31" + ); + } +} + +void hugemem_write16(hugemem_ptr_t to, uint_fast16_t val) +{ + asm( + "movw r30, %A0 \n\t" + "out %2, %C0 \n\t" + "st Z+, %A1 \n\t" + "st Z, %B1 \n\t" + "out %2, __zero_reg__ \n\t" + : + : "r"(to), "r"(val), "i"(&RAMPZ) + : "r30", "r31" + ); +} + +void hugemem_write32(hugemem_ptr_t to, uint_fast32_t val) +{ + asm( + "movw r30, %A0 \n\t" + "out %2, %C0 \n\t" + "st Z+, %A1 \n\t" + "st Z+, %B1 \n\t" + "st Z+, %C1 \n\t" + "st Z, %D1 \n\t" + "out %2, __zero_reg__ \n\t" + : + : "r"(to), "r"(val), "i"(&RAMPZ) + : "r30", "r31" + ); +} + +void hugemem_write_block(hugemem_ptr_t to, const void *from, size_t size) +{ + // Ensure that the address range to copy from is within 64 kB boundary. + Assert(((uint32_t)from + size) <= 0x10000); + + if (size > 0) { + asm volatile( + "movw r30, %A2 \n\t" + "out %3, %C2 \n\t" + "put_%=: \n\t" + "ld __tmp_reg__, X+ \n\t" + "st Z+, __tmp_reg__ \n\t" + "sbiw %A1, 1 \n\t" + "brne put_%= \n\t" + "out %3, __zero_reg__ \n\t" + : "+x"(from), "+w"(size) + : "r"(to), "i"(&RAMPZ) + : "r30", "r31" + ); + } +} +# endif /* __GNUC__ */ + +# ifdef __ICCAVR__ +void hugemem_read_block(void *to, const hugemem_ptr_t from, size_t size) +{ + uint8_t *to_ptr; + uint8_t __huge *from_ptr; + + // Ensure that the address range to copy to is within 64 kB boundary. + Assert(((uint32_t)to + size) <= 0x10000); + + to_ptr = (uint8_t *)to; + from_ptr = (uint8_t __huge *)from; + + for (; size > 0; size--) { + *to_ptr++ = *from_ptr++; + } +} + +void hugemem_write_block(hugemem_ptr_t to, const void *from, size_t size) +{ + uint8_t __huge *to_ptr; + uint8_t *from_ptr; + + // Ensure that the address range to copy from is within 64 kB boundary. + Assert(((uint32_t)from + size) <= 0x10000); + + to_ptr = (uint8_t __huge *)to; + from_ptr = (uint8_t *)from; + + for (; size > 0; size--) { + *to_ptr++ = *from_ptr++; + } +} +# endif /* __ICCAVR__ */ +#endif /* CONFIG_HAVE_HUGEMEM */ diff --git a/DSTAT1/src/asf/common/services/hugemem/avr8/hugemem.h b/DSTAT1/src/asf/common/services/hugemem/avr8/hugemem.h new file mode 100644 index 0000000..76a612b --- /dev/null +++ b/DSTAT1/src/asf/common/services/hugemem/avr8/hugemem.h @@ -0,0 +1,163 @@ +/** + * \file + * + * \brief Access to huge data memory with 8-bit AVR + * + * Do not include this file directly, but rather . + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef AVR8_HUGEMEM_H_INCLUDED +#define AVR8_HUGEMEM_H_INCLUDED + +#include +#include "conf_board.h" + +/** + * \weakgroup hugemem_group + * @{ + */ + +/** + * \internal + * \defgroup hugemem_avr8_group Hugemem implementation for 8-bit AVR. + * + * GCC does not have native support for 24-bit pointers, and therefore requires + * custom assembly functions for this purpose. The implemented functions leave + * RAMPZ cleared upon exit.\par + * + * If the chip does not support huge memory, i.e., \a CONFIG_HAVE_HUGEMEM is + * not defined, a generic implementation will be used. + */ + +#if defined(CONFIG_HAVE_HUGEMEM) || defined(__DOXYGEN__) +# if XMEGA && !(XMEGA_A1 || XMEGA_A1U) +# error CONFIG_HAVE_HUGEMEM is not supported on XMEGA parts without EBI. +# endif +# if defined(__GNUC__) || defined(__DOXYGEN__) +#include + +#include "compiler.h" + +typedef uint32_t hugemem_ptr_t; + +#define HUGEMEM_NULL 0 + +static inline uint_fast8_t hugemem_read8(const hugemem_ptr_t from) +{ + uint8_t value; + + asm volatile( + "movw r30, %A1 \n\t" + "out %2, %C1 \n\t" + "ld %0, Z \n\t" + "out %2, __zero_reg__ \n\t" + : "=r"(value) + : "r"(from), "i"(&RAMPZ) + : "r30", "r31" + ); + + return value; +} + +uint_fast16_t hugemem_read16(const hugemem_ptr_t from); +uint_fast32_t hugemem_read32(const hugemem_ptr_t from); + +static inline void hugemem_write8(hugemem_ptr_t to, uint_fast8_t val) +{ + asm volatile( + "movw r30, %A0 \n\t" + "out %2, %C0 \n\t" + "st Z, %1 \n\t" + "out %2, __zero_reg__ \n\t" + : + : "r"(to), "r"(val), "i"(&RAMPZ) + : "r30", "r31" + ); +} + +void hugemem_write16(hugemem_ptr_t to, uint_fast16_t val); +void hugemem_write32(hugemem_ptr_t to, uint_fast32_t val); + +# elif defined(__ICCAVR__) +#include + +typedef void __huge *hugemem_ptr_t; + +#define HUGEMEM_NULL NULL + +static inline uint_fast8_t hugemem_read8(const hugemem_ptr_t from) +{ + return *(volatile __huge uint8_t *)from; +} + +static inline uint_fast16_t hugemem_read16(const hugemem_ptr_t from) +{ + return *(volatile __huge uint16_t *)from; +} + +static inline uint_fast32_t hugemem_read32(const hugemem_ptr_t from) +{ + return *(volatile __huge uint32_t *)from; +} + +static inline void hugemem_write8(hugemem_ptr_t to, uint_fast8_t val) +{ + *(__huge uint8_t *)to = val; +} + +static inline void hugemem_write16(hugemem_ptr_t to, uint_fast16_t val) +{ + *(__huge uint16_t *)to = val; +} + +static inline void hugemem_write32(hugemem_ptr_t to, uint_fast32_t val) +{ + *(__huge uint32_t *)to = val; +} +# endif /* __ICCAVR__ */ + +void hugemem_read_block(void *to, const hugemem_ptr_t from, size_t size); +void hugemem_write_block(hugemem_ptr_t to, const void *from, size_t size); + +#else +# include +#endif /* CONFIG_HAVE_HUGEMEM */ +//@} + +#endif /* AVR8_HUGEMEM_H */ diff --git a/DSTAT1/src/asf/common/services/hugemem/generic/hugemem.h b/DSTAT1/src/asf/common/services/hugemem/generic/hugemem.h new file mode 100644 index 0000000..5f43e01 --- /dev/null +++ b/DSTAT1/src/asf/common/services/hugemem/generic/hugemem.h @@ -0,0 +1,112 @@ +/** + * \file + * + * \brief Generic implementation of huge data memory access + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef GENERIC_HUGEMEM_H_INCLUDED +#define GENERIC_HUGEMEM_H_INCLUDED + +#include +#include + +/** + * \weakgroup hugemem_group + * @{ + */ + +/** + * \internal + * \defgroup hugemem_generic_group Generic hugemem implementation. + * + * These functions are needed for code compatibility between 8- and 32-bit AVR, + * as well as a different application configurations on 8-bit AVR, i.e., if huge + * data memory is optional. + */ + +typedef void * hugemem_ptr_t; + +#define HUGEMEM_NULL NULL + +static inline uint8_t hugemem_read8(const hugemem_ptr_t from) +{ + return *(uint8_t *)from; +} + +static inline uint16_t hugemem_read16(const hugemem_ptr_t from) +{ + return *(uint16_t *)from; +} + +static inline uint32_t hugemem_read32(const hugemem_ptr_t from) +{ + return *(uint32_t *)from; +} + +static inline void hugemem_read_block(void *to, const hugemem_ptr_t from, + size_t size) +{ + memcpy(to, from, size); +} + +static inline void hugemem_write8(hugemem_ptr_t to, uint8_t val) +{ + *(uint8_t *)to = val; +} + +static inline void hugemem_write16(hugemem_ptr_t to, uint16_t val) +{ + *(uint16_t *)to = val; +} + + +static inline void hugemem_write32(hugemem_ptr_t to, uint32_t val) +{ + *(uint32_t *)to = val; +} + +static inline void hugemem_write_block(hugemem_ptr_t to, const void *from, + size_t size) +{ + memcpy(to, from, size); +} + +//@} + +#endif /* GENERIC_HUGEMEM_H */ diff --git a/DSTAT1/src/asf/common/services/hugemem/hugemem.h b/DSTAT1/src/asf/common/services/hugemem/hugemem.h new file mode 100644 index 0000000..fca4947 --- /dev/null +++ b/DSTAT1/src/asf/common/services/hugemem/hugemem.h @@ -0,0 +1,140 @@ +/** + * \file + * + * \brief Huge data memory space access + * + * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef HUGEMEM_H_INCLUDED +#define HUGEMEM_H_INCLUDED + +#include +#include + +#if defined(__AVR32__) || defined(__ICCAVR32__) +# include +#elif defined(__AVR__) || defined (__ICCAVR__) +# include +#else +# error Unknown architecture passed to hugemem interface. +# error Expected __AVR32__ or __AVR__. +#endif + +/** + * \defgroup hugemem_group Data in Huge Data Memory Space + * + * Due to shortcomings of the GCC compiler for 8-bit AVR, custom functions are + * needed for access to data beyond the 64 kB boundary, i.e., addresses that + * are larger than 16-bit. + * + * The definition of huge memory space can differ between architectures, so the + * implementation is architecture specific. + * + * This module supplies functions for copying a number of bytes between huge + * and 64 kB data memory space, and is needed solely for code compatibility + * across compilers. + * + * @{ + */ + +/** + * \typedef hugemem_ptr_t + * + * \brief Type to use for pointers to huge memory. + */ + +/** + * \def HUGEMEM_NULL + * + * \brief Hugemem null pointer, similar to NULL, but works across different + * platforms. + */ + +/** + * \fn uint_fast8_t hugemem_read8(const hugemem_ptr_t from) + * + * \brief Read 8-bit value stored at huge memory address \a from. + */ + +/** + * \fn uint_fast16_t hugemem_read16(const hugemem_ptr_t from) + * + * \brief Read 16-bit value stored at huge memory address \a from. + */ + +/** + * \fn void hugemem_read_block(void *to, const hugemem_ptr_t from, size_t size) + * + * \brief Read \a size bytes from huge memory address \a from into buffer at + * address \a to. + */ + +/** + * \fn uint_fast32_t hugemem_read32(const hugemem_ptr_t from) + * + * \brief Read 32-bit value stored at huge memory address \a from. + */ + +/** + * \fn void hugemem_write8(hugemem_ptr_t to, uint_fast8_t val) + * + * \brief Write 8-bit value \a val to huge memory address \a to. + */ + +/** + * \fn void hugemem_write16(hugemem_ptr_t to, uint_fast16_t val) + * + * \brief Write 16-bit value \a val to huge memory address \a to. + */ + +/** + * \fn void hugemem_write32(hugemem_ptr_t to, uint_fast32_t val) + * + * \brief Write 32-bit value \a val to huge memory address \a to. + */ + +/** + * \fn void hugemem_write_block(hugemem_ptr_t to, const void *from, size_t size) + * + * \brief Write \a size bytes from buffer at address \a from to huge memory + * address \a to. + */ + +//@} + +#endif /* HUGEMEM_H_INCLUDED */ diff --git a/DSTAT1/src/asf/common/services/ioport/ioport.h b/DSTAT1/src/asf/common/services/ioport/ioport.h new file mode 100644 index 0000000..a27fb7b --- /dev/null +++ b/DSTAT1/src/asf/common/services/ioport/ioport.h @@ -0,0 +1,515 @@ +/** + * \file + * + * \brief Common IOPORT service main header file for AVR, UC3 and ARM + * architectures. + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef IOPORT_H +#define IOPORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * \defgroup ioport_group Common IOPORT API + * + * See \ref ioport_quickstart. + * + * This is common IOPORT service for GPIO pin configuration and control in a + * standardized manner across the XMEGA, UC3 and ARM devices. + * + * Port pin control code is optimized for each platform, and should produce + * both compact and fast execution times when used with constant values. + * + * \section dependencies Dependencies + * This driver depends on the following modules: + * - \ref sysclk_group for clock speed and functions. + * @{ + */ + +/** + * \def IOPORT_CREATE_PIN(port, pin) + * \brief Create IOPORT pin number + * + * Create a IOPORT pin number for use with the IOPORT functions. + * + * \param port IOPORT port (e.g. PORTA, PA or PIOA depending on chosen + * architecture) + * \param pin IOPORT zero-based index of the I/O pin + */ + +/** \brief IOPORT pin directions */ +enum ioport_direction { + IOPORT_DIR_INPUT, /*!< IOPORT input direction */ + IOPORT_DIR_OUTPUT, /*!< IOPORT output direction */ +}; + +/** \brief IOPORT levels */ +enum ioport_value { + IOPORT_PIN_LEVEL_LOW, /*!< IOPORT pin value low */ + IOPORT_PIN_LEVEL_HIGH, /*!< IOPORT pin value high */ +}; + +/** \brief IOPORT edge sense modes */ +enum ioport_sense { + IOPORT_SENSE_BOTHEDGES, /*!< IOPORT sense both rising and falling edges */ + IOPORT_SENSE_RISING, /*!< IOPORT sense rising edges */ + IOPORT_SENSE_FALLING, /*!< IOPORT sense falling edges */ +}; + +#if XMEGA +# include "xmega/ioport.h" +# if defined(IOPORT_XMEGA_COMPAT) +# include "xmega/ioport_compat.h" +# endif +#elif UC3 +# include "uc3/ioport.h" +#elif SAM +# if SAM4L +# include "sam/ioport_gpio.h" +# else +# include "sam/ioport_pio.h" +# endif +#endif + +/** + * \brief Initializes the IOPORT service, ready for use. + * + * This function must be called before using any other functions in the IOPORT + * service. + */ +static inline void ioport_init(void) +{ + arch_ioport_init(); +} + +/** + * \brief Enable an IOPORT pin, based on a pin created with \ref + * IOPORT_CREATE_PIN(). + * + * \param pin IOPORT pin to enable + */ +static inline void ioport_enable_pin(ioport_pin_t pin) +{ + arch_ioport_enable_pin(pin); +} + +/** + * \brief Enable multiple pins in a single IOPORT port. + * + * \param port IOPORT port to enable + * \param mask Mask of pins within the port to enable + */ +static inline void ioport_enable_port(ioport_port_t port, + ioport_port_mask_t mask) +{ + arch_ioport_enable_port(port, mask); +} + +/** + * \brief Disable IOPORT pin, based on a pin created with \ref + * IOPORT_CREATE_PIN(). + * + * \param pin IOPORT pin to disable + */ +static inline void ioport_disable_pin(ioport_pin_t pin) +{ + arch_ioport_disable_pin(pin); +} + +/** + * \brief Disable multiple pins in a single IOPORT port. + * + * \param port IOPORT port to disable + * \param mask Pin mask of pins to disable + */ +static inline void ioport_disable_port(ioport_port_t port, + ioport_port_mask_t mask) +{ + arch_ioport_disable_port(port, mask); +} + +/** + * \brief Set multiple pin modes in a single IOPORT port, such as pull-up, + * pull-down, etc. configuration. + * + * \param port IOPORT port to configure + * \param mask Pin mask of pins to configure + * \param mode Mode masks to configure for the specified pins (\ref + * ioport_modes) + */ +static inline void ioport_set_port_mode(ioport_port_t port, + ioport_port_mask_t mask, ioport_mode_t mode) +{ + arch_ioport_set_port_mode(port, mask, mode); +} + +/** + * \brief Set pin mode for one single IOPORT pin. + * + * \param pin IOPORT pin to configure + * \param mode Mode masks to configure for the specified pin (\ref ioport_modes) + */ +static inline void ioport_set_pin_mode(ioport_pin_t pin, ioport_mode_t mode) +{ + arch_ioport_set_pin_mode(pin, mode); +} + +/** + * \brief Reset multiple pin modes in a specified IOPORT port to defaults. + * + * \param port IOPORT port to configure + * \param mask Mask of pins whose mode configuration is to be reset + */ +static inline void ioport_reset_port_mode(ioport_port_t port, + ioport_port_mask_t mask) +{ + arch_ioport_set_port_mode(port, mask, 0); +} + +/** + * \brief Reset pin mode configuration for a single IOPORT pin + * + * \param pin IOPORT pin to configure + */ +static inline void ioport_reset_pin_mode(ioport_pin_t pin) +{ + arch_ioport_set_pin_mode(pin, 0); +} + +/** + * \brief Set I/O direction for a group of pins in a single IOPORT. + * + * \param port IOPORT port to configure + * \param mask Pin mask of pins to configure + * \param dir Direction to set for the specified pins (\ref ioport_direction) + */ +static inline void ioport_set_port_dir(ioport_port_t port, + ioport_port_mask_t mask, enum ioport_direction dir) +{ + arch_ioport_set_port_dir(port, mask, dir); +} + +/** + * \brief Set direction for a single IOPORT pin. + * + * \param pin IOPORT pin to configure + * \param dir Direction to set for the specified pin (\ref ioport_direction) + */ +static inline void ioport_set_pin_dir(ioport_pin_t pin, + enum ioport_direction dir) +{ + arch_ioport_set_pin_dir(pin, dir); +} + +/** + * \brief Set an IOPORT pin to a specified logical value. + * + * \param pin IOPORT pin to configure + * \param level Logical value of the pin + */ +static inline void ioport_set_pin_level(ioport_pin_t pin, bool level) +{ + arch_ioport_set_pin_level(pin, level); +} + +/** + * \brief Set a group of IOPORT pins in a single port to a specified logical + * value. + * + * \param port IOPORT port to write to + * \param mask Pin mask of pins to modify + * \param level Level of the pins to be modified + */ +static inline void ioport_set_port_level(ioport_port_t port, + ioport_port_mask_t mask, ioport_port_mask_t level) +{ + arch_ioport_set_port_level(port, mask, level); +} + +/** + * \brief Get current value of an IOPORT pin, which has been configured as an + * input. + * + * \param pin IOPORT pin to read + * \return Current logical value of the specified pin + */ +static inline bool ioport_get_pin_level(ioport_pin_t pin) +{ + return arch_ioport_get_pin_level(pin); +} + +/** + * \brief Get current value of several IOPORT pins in a single port, which have + * been configured as an inputs. + * + * \param port IOPORT port to read + * \param mask Pin mask of pins to read + * \return Logical levels of the specified pins from the read port, returned as + * a mask. + */ +static inline ioport_port_mask_t ioport_get_port_level(ioport_pin_t port, + ioport_port_mask_t mask) +{ + return arch_ioport_get_port_level(port, mask); +} + +/** + * \brief Toggle the value of an IOPORT pin, which has previously configured as + * an output. + * + * \param pin IOPORT pin to toggle + */ +static inline void ioport_toggle_pin_level(ioport_pin_t pin) +{ + arch_ioport_toggle_pin_level(pin); +} + +/** + * \brief Toggle the values of several IOPORT pins located in a single port. + * + * \param port IOPORT port to modify + * \param mask Pin mask of pins to toggle + */ +static inline void ioport_toggle_port_level(ioport_port_t port, + ioport_port_mask_t mask) +{ + arch_ioport_toggle_port_level(port, mask); +} + +/** + * \brief Set the pin sense mode of a single IOPORT pin. + * + * \param pin IOPORT pin to configure + * \param pin_sense Edge to sense for the pin (\ref ioport_sense) + */ +static inline void ioport_set_pin_sense_mode(ioport_pin_t pin, + enum ioport_sense pin_sense) +{ + arch_ioport_set_pin_sense_mode(pin, pin_sense); +} + +/** + * \brief Set the pin sense mode of a multiple IOPORT pins on a single port. + * + * \param port IOPORT port to configure + * \param mask Bitmask if pins whose edge sense is to be configured + * \param pin_sense Edge to sense for the pins (\ref ioport_sense) + */ +static inline void ioport_set_port_sense_mode(ioport_port_t port, + ioport_port_mask_t mask, + enum ioport_sense pin_sense) +{ + arch_ioport_set_port_sense_mode(port, mask, pin_sense); +} + +/** + * \brief Convert a pin ID into a its port ID. + * + * \param pin IOPORT pin ID to convert + * \retval Port ID for the given pin ID + */ +static inline ioport_port_t ioport_pin_to_port_id(ioport_pin_t pin) +{ + return arch_ioport_pin_to_port_id(pin); +} + +/** + * \brief Convert a pin ID into a bitmask mask for the given pin on its port. + * + * \param pin IOPORT pin ID to convert + * \retval Bitmask with a bit set that corresponds to the given pin ID in its port + */ +static inline ioport_port_mask_t ioport_pin_to_mask(ioport_pin_t pin) +{ + return arch_ioport_pin_to_mask(pin); +} + +/** @} */ + +/** + * \page ioport_quickstart Quick start guide for the common IOPORT service + * + * This is the quick start guide for the \ref ioport_group, with + * step-by-step instructions on how to configure and use the service in a + * selection of use cases. + * + * The use cases contain several code fragments. The code fragments in the + * steps for setup can be copied into a custom initialization function, while + * the steps for usage can be copied into, e.g., the main application function. + * + * \section ioport_quickstart_basic Basic use case + * In this use case we will configure one IO pin for button input and one for + * LED control. Then it will read the button state and output it on the LED. + * + * \section ioport_quickstart_basic_setup Setup steps + * + * \subsection ioport_quickstart_basic_setup_code Example code + * \code + * #define MY_LED IOPORT_CREATE_PIN(PORTA, 5) + * #define MY_BUTTON IOPORT_CREATE_PIN(PORTA, 6) + * + * ioport_init(); + * + * ioport_set_pin_dir(MY_LED, IOPORT_DIR_OUTPUT); + * ioport_set_pin_dir(MY_BUTTON, IOPORT_DIR_INPUT); + * ioport_set_pin_mode(MY_BUTTON, IOPORT_MODE_PULLUP); + * \endcode + * + * \subsection ioport_quickstart_basic_setup_flow Workflow + * -# It's useful to give the GPIOs symbolic names and this can be done with + * the \ref IOPORT_CREATE_PIN macro. We define one for a LED and one for a + * button. + * - \code + * #define MY_LED IOPORT_CREATE_PIN(PORTA, 5) + * #define MY_BUTTON IOPORT_CREATE_PIN(PORTA, 6) + * \endcode + * - \note The usefulness of the \ref IOPORT_CREATE_PIN macro and port names + * differ between architectures: + * - XMEGA: Use \ref IOPORT_CREATE_PIN macro with port definitions + * PORTA, PORTB ... + * - UC3: Most convenient to pick up the device header file pin definition + * and us it directly. E.g.: AVR32_PIN_PB06 + * - SAM: Most convenient to pick up the device header file pin definition + * and us it directly. E.g.: PIO_PA5_IDX
+ * \ref IOPORT_CREATE_PIN can also be used with port definitions + * PIOA, PIOB ... + * -# Initialize the ioport service. This typically enables the IO module if + * needed. + * - \code ioport_init(); \endcode + * -# Set the LED GPIO as output: + * - \code ioport_set_pin_dir(MY_LED, IOPORT_DIR_OUTPUT); \endcode + * -# Set the button GPIO as input: + * - \code ioport_set_pin_dir(MY_BUTTON, IOPORT_DIR_INPUT); \endcode + * -# Enable pull-up for the button GPIO: + * - \code ioport_set_pin_mode(MY_BUTTON, IOPORT_MODE_PULLUP); \endcode + * + * \section ioport_quickstart_basic_usage Usage steps + * + * \subsection ioport_quickstart_basic_usage_code Example code + * \code + * bool value; + * + * value = ioport_get_pin_level(MY_BUTTON); + * ioport_set_pin_level(MY_LED, value); + * \endcode + * + * \subsection ioport_quickstart_basic_usage_flow Workflow + * -# Define a boolean variable for state storage: + * - \code bool value; \endcode + * -# Read out the button level into variable value: + * - \code value = ioport_get_pin_level(MY_BUTTON); \endcode + * -# Set the LED to read out value from the button: + * - \code ioport_set_pin_level(MY_LED, value); \endcode + * + * \section ioport_quickstart_advanced Advanced use cases + * - \subpage ioport_quickstart_use_case_1 : Port access + */ + +/** + * \page ioport_quickstart_use_case_1 Advanced use case doing port access + * + * In this case we will read out the pins from one whole port and write the + * read value to another port. + * + * \section ioport_quickstart_use_case_1_setup Setup steps + * + * \subsection ioport_quickstart_use_case_1_setup_code Example code + * \code + * #define IN_PORT IOPORT_PORTA + * #define OUT_PORT IOPORT_PORTB + * #define MASK 0x00000060 + * + * ioport_init(); + * + * ioport_set_port_dir(IN_PORT, MASK, IOPORT_DIR_INPUT); + * ioport_set_port_dir(OUT_PORT, MASK, IOPORT_DIR_OUTPUT); + * \endcode + * + * \subsection ioport_quickstart_basic_setup_flow Workflow + * -# It's useful to give the ports symbolic names: + * - \code + * #define IN_PORT IOPORT_PORTA + * #define OUT_PORT IOPORT_PORTB + * \endcode + * - \note The port names differ between architectures: + * - XMEGA: There are predefined names for ports: IOPORT_PORTA, + * IOPORT_PORTB ... + * - UC3: Use the index value of the different IO blocks: 0, 1 ... + * - SAM: There are predefined names for ports: IOPORT_PIOA, IOPORT_PIOB + * ... + * -# Also useful to define a mask for the bits to work with: + * - \code #define MASK 0x00000060 \endcode + * -# Initialize the ioport service. This typically enables the IO module if + * needed. + * - \code ioport_init(); \endcode + * -# Set one of the ports as input: + * - \code ioport_set_pin_dir(IN_PORT, MASK, IOPORT_DIR_INPUT); \endcode + * -# Set the other port as output: + * - \code ioport_set_pin_dir(OUT_PORT, MASK, IOPORT_DIR_OUTPUT); \endcode + * + * \section ioport_quickstart_basic_usage Usage steps + * + * \subsection ioport_quickstart_basic_usage_code Example code + * \code + * ioport_port_mask_t value; + * + * value = ioport_get_port_level(IN_PORT, MASK); + * ioport_set_port_level(OUT_PORT, MASK, value); + * \endcode + * + * \subsection ioport_quickstart_basic_usage_flow Workflow + * -# Define a variable for port date storage: + * - \code ioport_port_mask_t value; \endcode + * -# Read out from one port: + * - \code value = ioport_get_port_level(IN_PORT, MASK); \endcode + * -# Put the read data out on the other port: + * - \code ioport_set_port_level(OUT_PORT, MASK, value); \endcode + */ + +#ifdef __cplusplus +} +#endif + +#endif /* IOPORT_H */ diff --git a/DSTAT1/src/asf/common/services/ioport/xmega/ioport.h b/DSTAT1/src/asf/common/services/ioport/xmega/ioport.h new file mode 100644 index 0000000..5b2f21f --- /dev/null +++ b/DSTAT1/src/asf/common/services/ioport/xmega/ioport.h @@ -0,0 +1,337 @@ +/** + * \file + * + * \brief XMEGA architecture specific IOPORT service implementation header file. + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef IOPORT_XMEGA_H +#define IOPORT_XMEGA_H + +#define IOPORT_CREATE_PIN(port, pin) ((IOPORT_ ## port) * 8 + (pin)) +#define IOPORT_BASE_ADDRESS 0x600 +#define IOPORT_PORT_OFFSET 0x20 + +/** \name IOPORT port numbers */ +/** @{ */ +#if !XMEGA_B3 +# define IOPORT_PORTA 0 +#endif + +#define IOPORT_PORTB 1 +#define IOPORT_PORTC 2 +#define IOPORT_PORTD 3 + +#if !XMEGA_B3 +# define IOPORT_PORTE 4 +#endif + +#if XMEGA_A1 || XMEGA_A1U || XMEGA_A3 || XMEGA_A3U || XMEGA_A3B || XMEGA_A3BU ||\ + XMEGA_C3 || XMEGA_D3 +# define IOPORT_PORTF 5 +#endif + +#if XMEGA_B1 || XMEGA_B3 +# define IOPORT_PORTG 6 +#endif + +#if XMEGA_A1 || XMEGA_A1U +# define IOPORT_PORTH 7 +# define IOPORT_PORTJ 8 +# define IOPORT_PORTK 9 +#endif + +#if XMEGA_B1 || XMEGA_B3 +# define IOPORT_PORTM 11 +#endif + +#if XMEGA_A1 || XMEGA_A1U +# define IOPORT_PORTQ 14 +#endif + +#define IOPORT_PORTR 15 +/** @} */ + +/** + * \weakgroup ioport_group + * \section ioport_modes IOPORT Modes + * + * For details on these please see the XMEGA Manual. + * + * @{ + */ + +/** \name IOPORT Mode bit definitions */ +/** @{ */ +#define IOPORT_MODE_TOTEM (0x00 << 3) /*!< Totem-pole */ +#define IOPORT_MODE_BUSKEEPER (0x01 << 3) /*!< Buskeeper */ +#define IOPORT_MODE_PULLDOWN (0x02 << 3) /*!< Pull-down */ +#define IOPORT_MODE_PULLUP (0x03 << 3) /*!< Pull-up */ +#define IOPORT_MODE_WIREDOR (0x04 << 3) /*!< Wired OR */ +#define IOPORT_MODE_WIREDAND (0x05 << 3) /*!< Wired AND */ +#define IOPORT_MODE_WIREDORPULL (0x06 << 3) /*!< Wired OR with pull-down */ +#define IOPORT_MODE_WIREDANDPULL (0x07 << 3) /*!< Wired AND with pull-up */ +#define IOPORT_MODE_INVERT_PIN (0x01 << 6) /*!< Invert output and input */ +#define IOPORT_MODE_SLEW_RATE_LIMIT (0x01 << 7) /*!< Slew rate limiting */ +/** @} */ + +/** @} */ + +typedef uint8_t ioport_mode_t; +typedef uint8_t ioport_pin_t; +typedef uint8_t ioport_port_t; +typedef uint8_t ioport_port_mask_t; + +__always_inline static ioport_port_t arch_ioport_pin_to_port_id(ioport_pin_t pin) +{ + return pin >> 3; +} + +__always_inline static PORT_t *arch_ioport_port_to_base(ioport_port_t port) +{ + return (PORT_t *)((uintptr_t)IOPORT_BASE_ADDRESS + + (port * IOPORT_PORT_OFFSET)); +} + +__always_inline static PORT_t *arch_ioport_pin_to_base(ioport_pin_t pin) +{ + return arch_ioport_port_to_base(arch_ioport_pin_to_port_id(pin)); +} + +__always_inline static ioport_port_mask_t arch_ioport_pin_to_mask(ioport_pin_t pin) +{ + return 1U << (pin & 0x07); +} + +__always_inline static ioport_port_mask_t arch_ioport_pin_to_index(ioport_pin_t pin) +{ + return (pin & 0x07); +} + +__always_inline static void arch_ioport_init(void) +{ + +} + +__always_inline static void arch_ioport_enable_port(ioport_port_t port, + ioport_port_mask_t mask) +{ + PORT_t *base = arch_ioport_port_to_base(port); + volatile uint8_t *pin_ctrl = &base->PIN0CTRL; + + uint8_t flags = cpu_irq_save(); + + for (uint8_t i = 0; i < 8; i++) { + if (mask & arch_ioport_pin_to_mask(i)) { + pin_ctrl[i] &= ~PORT_ISC_gm; + } + } + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_enable_pin(ioport_pin_t pin) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + volatile uint8_t *pin_ctrl = + (&base->PIN0CTRL + arch_ioport_pin_to_index(pin)); + + uint8_t flags = cpu_irq_save(); + + *pin_ctrl &= ~PORT_ISC_gm; + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_disable_port(ioport_port_t port, + ioport_port_mask_t mask) +{ + PORT_t *base = arch_ioport_port_to_base(port); + volatile uint8_t *pin_ctrl = &base->PIN0CTRL; + + uint8_t flags = cpu_irq_save(); + + for (uint8_t i = 0; i < 8; i++) { + if (mask & arch_ioport_pin_to_mask(i)) { + pin_ctrl[i] |= PORT_ISC_INPUT_DISABLE_gc; + } + } + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_disable_pin(ioport_pin_t pin) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + volatile uint8_t *pin_ctrl = + (&base->PIN0CTRL + arch_ioport_pin_to_index(pin)); + + uint8_t flags = cpu_irq_save(); + + *pin_ctrl |= PORT_ISC_INPUT_DISABLE_gc; + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_set_port_mode(ioport_port_t port, + ioport_port_mask_t mask, ioport_mode_t mode) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + PORTCFG.MPCMASK = mask; + base->PIN0CTRL = mode; +} + +__always_inline static void arch_ioport_set_pin_mode(ioport_pin_t pin, + ioport_mode_t mode) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + PORTCFG.MPCMASK = arch_ioport_pin_to_mask(pin); + base->PIN0CTRL = mode; +} + +__always_inline static void arch_ioport_set_port_dir(ioport_port_t port, + ioport_port_mask_t mask, enum ioport_direction dir) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + if (dir == IOPORT_DIR_OUTPUT) { + base->DIRSET = mask; + } else if (dir == IOPORT_DIR_INPUT) { + base->DIRCLR = mask; + } +} + +__always_inline static void arch_ioport_set_pin_dir(ioport_pin_t pin, + enum ioport_direction dir) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + if (dir == IOPORT_DIR_OUTPUT) { + base->DIRSET = arch_ioport_pin_to_mask(pin); + } else if (dir == IOPORT_DIR_INPUT) { + base->DIRCLR = arch_ioport_pin_to_mask(pin); + } +} + +__always_inline static void arch_ioport_set_pin_level(ioport_pin_t pin, + bool level) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + if (level) { + base->OUTSET = arch_ioport_pin_to_mask(pin); + } else { + base->OUTCLR = arch_ioport_pin_to_mask(pin); + } +} + +__always_inline static void arch_ioport_set_port_level(ioport_port_t port, + ioport_port_mask_t mask, ioport_port_mask_t level) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + base->OUTSET = mask & level; + base->OUTCLR = mask & ~level; +} + +__always_inline static bool arch_ioport_get_pin_level(ioport_pin_t pin) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + return base->IN & arch_ioport_pin_to_mask(pin); +} + +__always_inline static ioport_port_mask_t arch_ioport_get_port_level( + ioport_port_t port, ioport_port_mask_t mask) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + return base->IN & mask; +} + +__always_inline static void arch_ioport_toggle_pin_level(ioport_pin_t pin) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + + base->OUTTGL = arch_ioport_pin_to_mask(pin); +} + +__always_inline static void arch_ioport_toggle_port_level(ioport_port_t port, + ioport_port_mask_t mask) +{ + PORT_t *base = arch_ioport_port_to_base(port); + + base->OUTTGL = mask; +} + +__always_inline static void arch_ioport_set_pin_sense_mode(ioport_pin_t pin, + enum ioport_sense pin_sense) +{ + PORT_t *base = arch_ioport_pin_to_base(pin); + volatile uint8_t *pin_ctrl = + (&base->PIN0CTRL + arch_ioport_pin_to_index(pin)); + + uint8_t flags = cpu_irq_save(); + + *pin_ctrl &= ~PORT_ISC_gm; + *pin_ctrl |= (pin_sense & PORT_ISC_gm); + + cpu_irq_restore(flags); +} + +__always_inline static void arch_ioport_set_port_sense_mode(ioport_port_t port, + ioport_port_mask_t mask, enum ioport_sense pin_sense) +{ + PORT_t *base = arch_ioport_port_to_base(port); + volatile uint8_t *pin_ctrl = &base->PIN0CTRL; + uint8_t new_sense_bits = (pin_sense & PORT_ISC_gm); + + uint8_t flags = cpu_irq_save(); + + for (uint8_t i = 0; i < 8; i++) { + if (mask & arch_ioport_pin_to_mask(i)) { + pin_ctrl[i] = (pin_ctrl[i] & ~PORT_ISC_gm) | new_sense_bits; + } + } + + cpu_irq_restore(flags); +} + +#endif /* IOPORT_XMEGA_H */ diff --git a/DSTAT1/src/asf/common/services/ioport/xmega/ioport_compat.c b/DSTAT1/src/asf/common/services/ioport/xmega/ioport_compat.c new file mode 100644 index 0000000..af81a81 --- /dev/null +++ b/DSTAT1/src/asf/common/services/ioport/xmega/ioport_compat.c @@ -0,0 +1,70 @@ +/** + * \file + * + * \brief XMEGA legacy IOPORT software compatibility driver interface. + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include "ioport_compat.h" + +#if defined(IOPORT_XMEGA_COMPAT) +void ioport_configure_port_pin(void *port, pin_mask_t pin_mask, + port_pin_flags_t flags) +{ + uint8_t pin; + + for (pin = 0; pin < 8; pin++) { + if (pin_mask & (1 << pin)) { + *((uint8_t *)port + PORT_PIN0CTRL + pin) = flags >> 8; + } + } + /* Select direction and initial pin state */ + if (flags & IOPORT_DIR_OUTPUT) { + if (flags & IOPORT_INIT_HIGH) { + *((uint8_t *)port + PORT_OUTSET) = pin_mask; + } else { + *((uint8_t *)port + PORT_OUTCLR) = pin_mask; + } + + *((uint8_t *)port + PORT_DIRSET) = pin_mask; + } else { + *((uint8_t *)port + PORT_DIRCLR) = pin_mask; + } +} + +#endif diff --git a/DSTAT1/src/asf/common/services/ioport/xmega/ioport_compat.h b/DSTAT1/src/asf/common/services/ioport/xmega/ioport_compat.h new file mode 100644 index 0000000..91ed6ec --- /dev/null +++ b/DSTAT1/src/asf/common/services/ioport/xmega/ioport_compat.h @@ -0,0 +1,315 @@ +/** + * \file + * + * \brief XMEGA legacy IOPORT software compatibility driver interface header + * file. + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef IOPORT_XMEGA_COMPAT_H_ +#define IOPORT_XMEGA_COMPAT_H_ + +#include "../ioport.h" + +/** + * \brief A pin mask + * + * This type is used to describe the port pin mask on the part. + */ +typedef uint8_t pin_mask_t; + +/** + * \brief A PORT pin + * + * This type is used to describe the PORT pins on the part. + */ +typedef uint8_t port_pin_t; + +/** + * \brief Pin configuration flags + * + * This is a bitmask containing configuration flags for the pins that shall be + * configured. + */ +typedef uint16_t port_pin_flags_t; + +/** + * \brief A port id + * + * This type is used to describe the port id on the part (0 is PORTA). + */ +typedef uint8_t port_id_t; + +/** \name Initial Output State Flags */ +/** @{ */ +#define IOPORT_INIT_LOW (0 << 1) /*!< Initial Output State Low */ +#define IOPORT_INIT_HIGH (1 << 1) /*!< Initial Output State High */ +/** @} */ + +/** \name Input/Sense Configuration Flags */ +/** @{ */ +#define IOPORT_BOTHEDGES (0 << 8) /*!< Sense Both Edges */ +#define IOPORT_RISING (1 << 8) /*!< Sense Rising Edge */ +#define IOPORT_FALLING (2 << 8) /*!< Sense Falling Edge */ +#define IOPORT_LEVEL (3 << 8) /*!< Sense Low Level */ +#define IOPORT_INPUT_DISABLE (7 << 8) /*!< Input Buffer Disabled */ +/** @} */ + +/** \name Output and Pull Configuration Flags */ +/** @{ */ +#define IOPORT_TOTEM (0 << 11) /*!< Normal push/pull output */ +#define IOPORT_BUSKEEPER (1 << 11) /*!< Bus Keeper */ +#define IOPORT_PULL_DOWN (2 << 11) /*!< Pull-Down (when input) */ +#define IOPORT_PULL_UP (3 << 11) /*!< Pull-Up (when input) */ +#define IOPORT_WIRED_OR (4 << 11) /*!< Wired OR */ +#define IOPORT_WIRED_AND (5 << 11) /*!< Wired AND */ +#define IOPORT_WIRED_OR_PULL_DOWN (6 << 11) /*!< Wired OR and Pull-Down */ +#define IOPORT_WIRED_AND_PULL_UP (7 << 11) /*!< Wired AND and Pull-Up */ +/** @} */ + +/** \name Inverted I/O Configuration Flags */ +/** @{ */ +#define IOPORT_INV_ENABLED (1 << 14) /*!< I/O is Inverted */ +#define IOPORT_INV_DISABLE (0 << 14) /*!< I/O is Not Inverted */ +/** @} */ + +/** \name Slew Rate Limit Configuration Flags */ +/** @{ */ +#define IOPORT_SRL_ENABLED (1 << 15) /*!< Slew Rate Limit Enabled */ +#define IOPORT_SRL_DISABLED (0 << 15) /*!< Slew Rate Limit Disabled */ +/** @} */ + +/** + * \internal + * \name PORT fields structure offset + * + * These macros are used to compute the field offset number with the PORT_t + * structure. + */ +/** @{ */ +#define PORT_DIR 0x00 /*!< Data Direction */ +#define PORT_DIRSET 0x01 /*!< Data Direction Set */ +#define PORT_DIRCLR 0x02 /*!< Data Direction Clear */ +#define PORT_DIRTGL 0x03 /*!< Data Direction Toggle */ +#define PORT_OUT 0x04 /*!< Data Output Value */ +#define PORT_OUTSET 0x05 /*!< Data Output Value Set */ +#define PORT_OUTCLR 0x06 /*!< Data Output Value Clear */ +#define PORT_OUTTGL 0x07 /*!< Data Output Value Toggle */ +#define PORT_IN 0x08 /*!< Data Input Value */ +#define PORT_INTCTRL 0x09 /*!< Interrupt Control */ +#define PORT_INT0MASK 0x0A /*!< Interrupt 0 Mask */ +#define PORT_INT1MASK 0x0B /*!< Interrupt 1 Mask */ +#define PORT_INTFLAGS 0x0C /*!< Interrupt Flags */ +#define PORT_PIN0CTRL 0x10 /*!< Pin 0 Configuration */ +#define PORT_PIN1CTRL 0x11 /*!< Pin 1 Configuration */ +#define PORT_PIN2CTRL 0x12 /*!< Pin 2 Configuration */ +#define PORT_PIN3CTRL 0x13 /*!< Pin 3 Configuration */ +#define PORT_PIN4CTRL 0x14 /*!< Pin 4 Configuration */ +#define PORT_PIN5CTRL 0x15 /*!< Pin 5 Configuration */ +#define PORT_PIN6CTRL 0x16 /*!< Pin 6 Configuration */ +#define PORT_PIN7CTRL 0x17 /*!< Pin 7 Configuration */ +/** @} */ + +static inline PORT_t *ioport_pin_to_port(port_pin_t pin) +{ + return arch_ioport_pin_to_base(pin); +} + +static inline PORT_t *ioport_id_pin_to_port(port_id_t port) +{ + return arch_ioport_port_to_base(port); +} + +/** + * \brief Configure the IO PORT pin function for a set of pins on a port + * + * \param port Pointer to the port + * \param pin_mask Mask containing the pins that should be configured + * \param flags Bitmask of flags specifying additional configuration + * parameters. + */ +void ioport_configure_port_pin(void *port, pin_mask_t pin_mask, + port_pin_flags_t flags); + +/** + * \brief Select the port function for a single pin + * + * \param pin The pin to configure + * \param flags Bitmask of flags specifying additional configuration + * parameters. + */ +static inline void ioport_configure_pin(port_pin_t pin, port_pin_flags_t flags) +{ + ioport_configure_port_pin(arch_ioport_pin_to_base(pin), + arch_ioport_pin_to_mask(pin), flags); +} + +/** + * \brief Configure a group of I/O pins on a specified port number + * + * \param port The port number + * \param pin_mask The pin mask to configure + * \param flags Bitmask of flags specifying additional configuration + * parameters. + */ +static inline void ioport_configure_group(port_id_t port, pin_mask_t pin_mask, + port_pin_flags_t flags) +{ + ioport_configure_port_pin(arch_ioport_port_to_base(port), pin_mask, flags); +} + +/** + * \brief Drive a PORT pin to a given state + * + * This function will only have an effect if \a pin is configured as + * an output. + * + * \param pin A number identifying the pin to act on. + * \param value The desired state of the pin. \a true means drive the + * pin high (towards Vdd), while \a false means drive the pin low + * (towards Vss). + */ +static inline void ioport_set_value(port_pin_t pin, bool value) +{ + arch_ioport_set_pin_level(pin, value); +} + +/** + * \brief Drive a PORT pin to a low level + * + * This function will only have an effect if \a pin is configured as + * an output. + * + * \param pin A number identifying the pin to act on. + */ +static inline void ioport_set_pin_low(port_pin_t pin) +{ + arch_ioport_set_pin_level(pin, false); +} + +/** + * \brief Drive a PORT pin to a high level + * + * This function will only have an effect if \a pin is configured as + * an output. + * + * \param pin A number identifying the pin to act on. + */ +static inline void ioport_set_pin_high(port_pin_t pin) +{ + arch_ioport_set_pin_level(pin, true); +} + +/** + * \brief Read the current state of a PORT pin + * + * \param pin A number identifying the pin to read. + * \retval true The pin is currently high (close to Vdd) + * \retval false The pin is currently low (close to Vss) + */ +static inline bool ioport_get_value(port_pin_t pin) +{ + return arch_ioport_get_pin_level(pin); +} + +/** + * \brief Read the current state of a PORT pin and test high level + * + * \param pin A number identifying the pin to read. + * \retval true The pin is currently high (close to Vdd) + * \retval false The pin is currently low (close to Vss) + */ +static inline bool ioport_pin_is_high(port_pin_t pin) +{ + return (arch_ioport_get_pin_level(pin) == true); +} + +/** + * \brief Read the current state of a PORT pin and test high level + * + * \param pin A number identifying the pin to read. + * \retval true The pin is currently high (close to Vdd) + * \retval false The pin is currently low (close to Vss) + */ +static inline bool ioport_pin_is_low(port_pin_t pin) +{ + return (arch_ioport_get_pin_level(pin) == false); +} + +/** + * \brief Toggle the current state of a PORT pin + * + * \param pin A number identifying the pin to act on. + */ +static inline void ioport_toggle_pin(port_pin_t pin) +{ + arch_ioport_toggle_pin_level(pin); +} + +/*! \brief Drives a group of I/O pin of a port to high level. + * + * \param port_id The port number. + * \param port_mask The mask. + */ +static inline void ioport_set_group_high(port_id_t port_id, + pin_mask_t port_mask) +{ + arch_ioport_set_port_level(port_id, port_mask, port_mask); +} + +/*! \brief Drives a group of I/O pin of a port to low level. + * + * \param port_id The port number. + * \param port_mask The mask. + */ +static inline void ioport_set_group_low(port_id_t port_id, pin_mask_t port_mask) +{ + arch_ioport_set_port_level(port_id, port_mask, 0); +} + +/*! \brief Toggles a group of I/O pin of a port. + * + * \param port_id The port number. + * \param port_mask The mask. + */ +static inline void ioport_tgl_group(port_id_t port_id, pin_mask_t port_mask) +{ + arch_ioport_toggle_port_level(port_id, port_mask); +} + +#endif /* IOPORT_COMPAT_H_ */ diff --git a/DSTAT1/src/asf/common/utils/parts.h b/DSTAT1/src/asf/common/utils/parts.h new file mode 100644 index 0000000..532e36b --- /dev/null +++ b/DSTAT1/src/asf/common/utils/parts.h @@ -0,0 +1,671 @@ +/** + * \file + * + * \brief Atmel part identification macros + * + * Copyright (C) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef ATMEL_PARTS_H +#define ATMEL_PARTS_H + +/** + * \defgroup part_macros_group Atmel part identification macros + * + * This collection of macros identify which series and families that the various + * Atmel parts belong to. These can be used to select part-dependent sections of + * code at compile time. + * + * @{ + */ + +/** + * \name Convenience macros for part checking + * @{ + */ +//! Check GCC and IAR part definition for 8-bit AVR +#define AVR8_PART_IS_DEFINED(part) \ + (defined(__ ## part ## __) || defined(__AVR_ ## part ## __)) + +//! Check GCC and IAR part definition for 32-bit AVR +#define AVR32_PART_IS_DEFINED(part) \ + (defined(__AT32 ## part ## __) || defined(__AVR32_ ## part ## __)) + +//! Check GCC and IAR part definition for SAM +#define SAM_PART_IS_DEFINED(part) (defined(__ ## part ## __)) +/** @} */ + +/** + * \defgroup uc3_part_macros_group AVR UC3 parts + * @{ + */ + +/** + * \name AVR UC3 A series + * @{ + */ +#define UC3A0 ( \ + AVR32_PART_IS_DEFINED(UC3A0128) || \ + AVR32_PART_IS_DEFINED(UC3A0256) || \ + AVR32_PART_IS_DEFINED(UC3A0512) \ + ) + +#define UC3A1 ( \ + AVR32_PART_IS_DEFINED(UC3A1128) || \ + AVR32_PART_IS_DEFINED(UC3A1256) || \ + AVR32_PART_IS_DEFINED(UC3A1512) \ + ) + +#define UC3A3 ( \ + AVR32_PART_IS_DEFINED(UC3A364) || \ + AVR32_PART_IS_DEFINED(UC3A364S) || \ + AVR32_PART_IS_DEFINED(UC3A3128) || \ + AVR32_PART_IS_DEFINED(UC3A3128S) || \ + AVR32_PART_IS_DEFINED(UC3A3256) || \ + AVR32_PART_IS_DEFINED(UC3A3256S) \ + ) + +#define UC3A4 ( \ + AVR32_PART_IS_DEFINED(UC3A464) || \ + AVR32_PART_IS_DEFINED(UC3A464S) || \ + AVR32_PART_IS_DEFINED(UC3A4128) || \ + AVR32_PART_IS_DEFINED(UC3A4128S) || \ + AVR32_PART_IS_DEFINED(UC3A4256) || \ + AVR32_PART_IS_DEFINED(UC3A4256S) \ + ) +/** @} */ + +/** + * \name AVR UC3 B series + * @{ + */ +#define UC3B0 ( \ + AVR32_PART_IS_DEFINED(UC3B064) || \ + AVR32_PART_IS_DEFINED(UC3B0128) || \ + AVR32_PART_IS_DEFINED(UC3B0256) || \ + AVR32_PART_IS_DEFINED(UC3B0512) \ + ) + +#define UC3B1 ( \ + AVR32_PART_IS_DEFINED(UC3B164) || \ + AVR32_PART_IS_DEFINED(UC3B1128) || \ + AVR32_PART_IS_DEFINED(UC3B1256) || \ + AVR32_PART_IS_DEFINED(UC3B1512) \ + ) +/** @} */ + +/** + * \name AVR UC3 C series + * @{ + */ +#define UC3C0 ( \ + AVR32_PART_IS_DEFINED(UC3C064C) || \ + AVR32_PART_IS_DEFINED(UC3C0128C) || \ + AVR32_PART_IS_DEFINED(UC3C0256C) || \ + AVR32_PART_IS_DEFINED(UC3C0512C) \ + ) + +#define UC3C1 ( \ + AVR32_PART_IS_DEFINED(UC3C164C) || \ + AVR32_PART_IS_DEFINED(UC3C1128C) || \ + AVR32_PART_IS_DEFINED(UC3C1256C) || \ + AVR32_PART_IS_DEFINED(UC3C1512C) \ + ) + +#define UC3C2 ( \ + AVR32_PART_IS_DEFINED(UC3C264C) || \ + AVR32_PART_IS_DEFINED(UC3C2128C) || \ + AVR32_PART_IS_DEFINED(UC3C2256C) || \ + AVR32_PART_IS_DEFINED(UC3C2512C) \ + ) +/** @} */ + +/** + * \name AVR UC3 D series + * @{ + */ +#define UC3D3 ( \ + AVR32_PART_IS_DEFINED(UC64D3) || \ + AVR32_PART_IS_DEFINED(UC128D3) \ + ) + +#define UC3D4 ( \ + AVR32_PART_IS_DEFINED(UC64D4) || \ + AVR32_PART_IS_DEFINED(UC128D4) \ + ) +/** @} */ + +/** + * \name AVR UC3 L series + * @{ + */ +#define UC3L0 ( \ + AVR32_PART_IS_DEFINED(UC3L016) || \ + AVR32_PART_IS_DEFINED(UC3L032) || \ + AVR32_PART_IS_DEFINED(UC3L064) \ + ) + +#define UC3L0128 ( \ + AVR32_PART_IS_DEFINED(UC3L0128) \ + ) + +#define UC3L0256 ( \ + AVR32_PART_IS_DEFINED(UC3L0256) \ + ) + +#define UC3L3 ( \ + AVR32_PART_IS_DEFINED(UC64L3U) || \ + AVR32_PART_IS_DEFINED(UC128L3U) || \ + AVR32_PART_IS_DEFINED(UC256L3U) \ + ) + +#define UC3L4 ( \ + AVR32_PART_IS_DEFINED(UC64L4U) || \ + AVR32_PART_IS_DEFINED(UC128L4U) || \ + AVR32_PART_IS_DEFINED(UC256L4U) \ + ) + +#define UC3L3_L4 (UC3L3 || UC3L4) +/** @} */ + +/** + * \name AVR UC3 families + * @{ + */ +/** AVR UC3 A family */ +#define UC3A (UC3A0 || UC3A1 || UC3A3 || UC3A4) + +/** AVR UC3 B family */ +#define UC3B (UC3B0 || UC3B1) + +/** AVR UC3 C family */ +#define UC3C (UC3C0 || UC3C1 || UC3C2) + +/** AVR UC3 D family */ +#define UC3D (UC3D3 || UC3D4) + +/** AVR UC3 L family */ +#define UC3L (UC3L0 || UC3L0128 || UC3L0256 || UC3L3_L4) +/** @} */ + +/** AVR UC3 product line */ +#define UC3 (UC3A || UC3B || UC3C || UC3D || UC3L) + +/** @} */ + +/** + * \defgroup xmega_part_macros_group AVR XMEGA parts + * @{ + */ + +/** + * \name AVR XMEGA A series + * @{ + */ +#define XMEGA_A1 ( \ + AVR8_PART_IS_DEFINED(ATxmega64A1) || \ + AVR8_PART_IS_DEFINED(ATxmega128A1) \ + ) + +#define XMEGA_A3 ( \ + AVR8_PART_IS_DEFINED(ATxmega64A3) || \ + AVR8_PART_IS_DEFINED(ATxmega128A3) || \ + AVR8_PART_IS_DEFINED(ATxmega192A3) || \ + AVR8_PART_IS_DEFINED(ATxmega256A3) \ + ) + +#define XMEGA_A3B ( \ + AVR8_PART_IS_DEFINED(ATxmega256A3B) \ + ) + +#define XMEGA_A4 ( \ + AVR8_PART_IS_DEFINED(ATxmega16A4) || \ + AVR8_PART_IS_DEFINED(ATxmega32A4) \ + ) +/** @} */ + +/** + * \name AVR XMEGA AU series + * @{ + */ +#define XMEGA_A1U ( \ + AVR8_PART_IS_DEFINED(ATxmega64A1U) || \ + AVR8_PART_IS_DEFINED(ATxmega128A1U) \ + ) + +#define XMEGA_A3U ( \ + AVR8_PART_IS_DEFINED(ATxmega64A3U) || \ + AVR8_PART_IS_DEFINED(ATxmega128A3U) || \ + AVR8_PART_IS_DEFINED(ATxmega192A3U) || \ + AVR8_PART_IS_DEFINED(ATxmega256A3U) \ + ) + +#define XMEGA_A3BU ( \ + AVR8_PART_IS_DEFINED(ATxmega256A3BU) \ + ) + +#define XMEGA_A4U ( \ + AVR8_PART_IS_DEFINED(ATxmega16A4U) || \ + AVR8_PART_IS_DEFINED(ATxmega32A4U) || \ + AVR8_PART_IS_DEFINED(ATxmega64A4U) || \ + AVR8_PART_IS_DEFINED(ATxmega128A4U) \ + ) +/** @} */ + +/** + * \name AVR XMEGA B series + * @{ + */ +#define XMEGA_B1 ( \ + AVR8_PART_IS_DEFINED(ATxmega64B1) || \ + AVR8_PART_IS_DEFINED(ATxmega128B1) \ + ) + +#define XMEGA_B3 ( \ + AVR8_PART_IS_DEFINED(ATxmega64B3) || \ + AVR8_PART_IS_DEFINED(ATxmega128B3) \ + ) +/** @} */ + +/** + * \name AVR XMEGA C series + * @{ + */ +#define XMEGA_C3 ( \ + AVR8_PART_IS_DEFINED(ATxmega384C3) || \ + AVR8_PART_IS_DEFINED(ATxmega256C3) || \ + AVR8_PART_IS_DEFINED(ATxmega128C3) || \ + AVR8_PART_IS_DEFINED(ATxmega64C3) \ + ) + +#define XMEGA_C4 ( \ + AVR8_PART_IS_DEFINED(ATxmega32C4) || \ + AVR8_PART_IS_DEFINED(ATxmega16C4) \ + ) +/** @} */ + +/** + * \name AVR XMEGA D series + * @{ + */ +#define XMEGA_D3 ( \ + AVR8_PART_IS_DEFINED(ATxmega64D3) || \ + AVR8_PART_IS_DEFINED(ATxmega128D3) || \ + AVR8_PART_IS_DEFINED(ATxmega192D3) || \ + AVR8_PART_IS_DEFINED(ATxmega256D3) || \ + AVR8_PART_IS_DEFINED(ATxmega384D3) \ + ) + +#define XMEGA_D4 ( \ + AVR8_PART_IS_DEFINED(ATxmega16D4) || \ + AVR8_PART_IS_DEFINED(ATxmega32D4) || \ + AVR8_PART_IS_DEFINED(ATxmega64D4) || \ + AVR8_PART_IS_DEFINED(ATxmega128D4) \ + ) +/** @} */ + +/** + * \name AVR XMEGA families + * @{ + */ +/** AVR XMEGA A family */ +#define XMEGA_A (XMEGA_A1 || XMEGA_A3 || XMEGA_A3B || XMEGA_A4) + +/** AVR XMEGA AU family */ +#define XMEGA_AU (XMEGA_A1U || XMEGA_A3U || XMEGA_A3BU || XMEGA_A4U) + +/** AVR XMEGA B family */ +#define XMEGA_B (XMEGA_B1 || XMEGA_B3) + +/** AVR XMEGA C family */ +#define XMEGA_C (XMEGA_C3 || XMEGA_C4) + +/** AVR XMEGA D family */ +#define XMEGA_D (XMEGA_D3 || XMEGA_D4) +/** @} */ + +/** AVR XMEGA product line */ +#define XMEGA (XMEGA_A || XMEGA_AU || XMEGA_B || XMEGA_C || XMEGA_D) + +/** @} */ + +/** + * \defgroup mega_part_macros_group megaAVR parts + * + * \note These megaAVR groupings are based on the groups in AVR Libc for the + * part header files. They are not names of official megaAVR device series or + * families. + * + * @{ + */ + +/** + * \name ATmegaxx0/xx1 subgroups + * @{ + */ +#define MEGA_XX0 ( \ + AVR8_PART_IS_DEFINED(ATmega640) || \ + AVR8_PART_IS_DEFINED(ATmega1280) || \ + AVR8_PART_IS_DEFINED(ATmega2560) \ + ) + +#define MEGA_XX1 ( \ + AVR8_PART_IS_DEFINED(ATmega1281) || \ + AVR8_PART_IS_DEFINED(ATmega2561) \ + ) +/** @} */ + +/** + * \name megaAVR groups + * @{ + */ +/** ATmegaxx0/xx1 group */ +#define MEGA_XX0_1 (MEGA_XX0 || MEGA_XX1) + +/** ATmegaxx4 group */ +#define MEGA_XX4 ( \ + AVR8_PART_IS_DEFINED(ATmega164A) || \ + AVR8_PART_IS_DEFINED(ATmega164PA) || \ + AVR8_PART_IS_DEFINED(ATmega324) || \ + AVR8_PART_IS_DEFINED(ATmega324A) || \ + AVR8_PART_IS_DEFINED(ATmega324PA) || \ + AVR8_PART_IS_DEFINED(ATmega644) || \ + AVR8_PART_IS_DEFINED(ATmega644A) || \ + AVR8_PART_IS_DEFINED(ATmega644PA) || \ + AVR8_PART_IS_DEFINED(ATmega1284P) || \ + AVR8_PART_IS_DEFINED(ATmega128RFA1) \ + ) + +/** ATmegaxx4 group */ +#define MEGA_XX4_A ( \ + AVR8_PART_IS_DEFINED(ATmega164A) || \ + AVR8_PART_IS_DEFINED(ATmega164PA) || \ + AVR8_PART_IS_DEFINED(ATmega324A) || \ + AVR8_PART_IS_DEFINED(ATmega324PA) || \ + AVR8_PART_IS_DEFINED(ATmega644A) || \ + AVR8_PART_IS_DEFINED(ATmega644PA) || \ + AVR8_PART_IS_DEFINED(ATmega1284P) \ + ) + +/** ATmegaxx8 group */ +#define MEGA_XX8 ( \ + AVR8_PART_IS_DEFINED(ATmega48) || \ + AVR8_PART_IS_DEFINED(ATmega48A) || \ + AVR8_PART_IS_DEFINED(ATmega48PA) || \ + AVR8_PART_IS_DEFINED(ATmega88) || \ + AVR8_PART_IS_DEFINED(ATmega88A) || \ + AVR8_PART_IS_DEFINED(ATmega88PA) || \ + AVR8_PART_IS_DEFINED(ATmega168) || \ + AVR8_PART_IS_DEFINED(ATmega168A) || \ + AVR8_PART_IS_DEFINED(ATmega168PA) || \ + AVR8_PART_IS_DEFINED(ATmega328) || \ + AVR8_PART_IS_DEFINED(ATmega328P) \ + ) + +/** ATmegaxx8A/P/PA group */ +#define MEGA_XX8_A ( \ + AVR8_PART_IS_DEFINED(ATmega48A) || \ + AVR8_PART_IS_DEFINED(ATmega48PA) || \ + AVR8_PART_IS_DEFINED(ATmega88A) || \ + AVR8_PART_IS_DEFINED(ATmega88PA) || \ + AVR8_PART_IS_DEFINED(ATmega168A) || \ + AVR8_PART_IS_DEFINED(ATmega168PA) || \ + AVR8_PART_IS_DEFINED(ATmega328P) \ + ) + +/** ATmegaxx group */ +#define MEGA_XX ( \ + AVR8_PART_IS_DEFINED(ATmega16) || \ + AVR8_PART_IS_DEFINED(ATmega16A) || \ + AVR8_PART_IS_DEFINED(ATmega32) || \ + AVR8_PART_IS_DEFINED(ATmega32A) || \ + AVR8_PART_IS_DEFINED(ATmega64) || \ + AVR8_PART_IS_DEFINED(ATmega64A) || \ + AVR8_PART_IS_DEFINED(ATmega128) || \ + AVR8_PART_IS_DEFINED(ATmega128A) \ + ) + +/** ATmegaxxA/P/PA group */ +#define MEGA_XX_A ( \ + AVR8_PART_IS_DEFINED(ATmega16A) || \ + AVR8_PART_IS_DEFINED(ATmega32A) || \ + AVR8_PART_IS_DEFINED(ATmega64A) || \ + AVR8_PART_IS_DEFINED(ATmega128A) \ + ) + +/** Unspecified group */ +#define MEGA_UNSPECIFIED ( \ + AVR8_PART_IS_DEFINED(ATmega16) || \ + AVR8_PART_IS_DEFINED(ATmega16A) || \ + AVR8_PART_IS_DEFINED(ATmega32) || \ + AVR8_PART_IS_DEFINED(ATmega32A) || \ + AVR8_PART_IS_DEFINED(ATmega64) || \ + AVR8_PART_IS_DEFINED(ATmega64A) || \ + AVR8_PART_IS_DEFINED(ATmega128) || \ + AVR8_PART_IS_DEFINED(ATmega128A) || \ + AVR8_PART_IS_DEFINED(ATmega169P) || \ + AVR8_PART_IS_DEFINED(ATmega169PA) || \ + AVR8_PART_IS_DEFINED(ATmega329P) || \ + AVR8_PART_IS_DEFINED(ATmega329PA) \ + ) +/** @} */ + +/** megaAVR product line */ +#define MEGA (MEGA_XX0_1 || MEGA_XX4 || MEGA_XX8 || MEGA_XX || MEGA_UNSPECIFIED) + +/** @} */ + +/** + * \defgroup sam_part_macros_group SAM parts + * @{ + */ + +/** + * \name SAM3S series + * @{ + */ +#define SAM3S1 ( \ + SAM_PART_IS_DEFINED(SAM3S1A) || \ + SAM_PART_IS_DEFINED(SAM3S1B) || \ + SAM_PART_IS_DEFINED(SAM3S1C) \ + ) + +#define SAM3S2 ( \ + SAM_PART_IS_DEFINED(SAM3S2A) || \ + SAM_PART_IS_DEFINED(SAM3S2B) || \ + SAM_PART_IS_DEFINED(SAM3S2C) \ + ) + +#define SAM3S4 ( \ + SAM_PART_IS_DEFINED(SAM3S4A) || \ + SAM_PART_IS_DEFINED(SAM3S4B) || \ + SAM_PART_IS_DEFINED(SAM3S4C) \ + ) + +#define SAM3S8 ( \ + SAM_PART_IS_DEFINED(SAM3S8B) || \ + SAM_PART_IS_DEFINED(SAM3S8C) \ + ) + +#define SAM3SD8 ( \ + SAM_PART_IS_DEFINED(SAM3SD8B) || \ + SAM_PART_IS_DEFINED(SAM3SD8C) \ + ) +/** @} */ + +/** + * \name SAM3U series + * @{ + */ +#define SAM3U1 ( \ + SAM_PART_IS_DEFINED(SAM3U1C) || \ + SAM_PART_IS_DEFINED(SAM3U1E) \ + ) + +#define SAM3U2 ( \ + SAM_PART_IS_DEFINED(SAM3U2C) || \ + SAM_PART_IS_DEFINED(SAM3U2E) \ + ) + +#define SAM3U4 ( \ + SAM_PART_IS_DEFINED(SAM3U4C) || \ + SAM_PART_IS_DEFINED(SAM3U4E) \ + ) +/** @} */ + +/** + * \name SAM3N series + * @{ + */ +#define SAM3N1 ( \ + SAM_PART_IS_DEFINED(SAM3N1A) || \ + SAM_PART_IS_DEFINED(SAM3N1B) || \ + SAM_PART_IS_DEFINED(SAM3N1C) \ + ) + +#define SAM3N2 ( \ + SAM_PART_IS_DEFINED(SAM3N2A) || \ + SAM_PART_IS_DEFINED(SAM3N2B) || \ + SAM_PART_IS_DEFINED(SAM3N2C) \ + ) + +#define SAM3N4 ( \ + SAM_PART_IS_DEFINED(SAM3N4A) || \ + SAM_PART_IS_DEFINED(SAM3N4B) || \ + SAM_PART_IS_DEFINED(SAM3N4C) \ + ) +/** @} */ + +/** + * \name SAM3X series + * @{ + */ +#define SAM3X4 ( \ + SAM_PART_IS_DEFINED(SAM3X4C) || \ + SAM_PART_IS_DEFINED(SAM3X4E) \ + ) + +#define SAM3X8 ( \ + SAM_PART_IS_DEFINED(SAM3X8C) || \ + SAM_PART_IS_DEFINED(SAM3X8E) || \ + SAM_PART_IS_DEFINED(SAM3X8H) \ + ) +/** @} */ + +/** + * \name SAM3A series + * @{ + */ +#define SAM3A4 ( \ + SAM_PART_IS_DEFINED(SAM3A4C) \ + ) + +#define SAM3A8 ( \ + SAM_PART_IS_DEFINED(SAM3A8C) \ + ) +/** @} */ + +/** + * \name SAM4S series + * @{ + */ +#define SAM4S8 ( \ + SAM_PART_IS_DEFINED(SAM4S8B) || \ + SAM_PART_IS_DEFINED(SAM4S8C) \ + ) + +#define SAM4S16 ( \ + SAM_PART_IS_DEFINED(SAM4S16B) || \ + SAM_PART_IS_DEFINED(SAM4S16C) \ + ) +/** @} */ + +/** + * \name SAM4L series + * @{ + */ +#define SAM4LS ( \ + SAM_PART_IS_DEFINED(ATSAM4LS2A) || \ + SAM_PART_IS_DEFINED(ATSAM4LS2B) || \ + SAM_PART_IS_DEFINED(ATSAM4LS2C) || \ + SAM_PART_IS_DEFINED(ATSAM4LS4A) || \ + SAM_PART_IS_DEFINED(ATSAM4LS4B) || \ + SAM_PART_IS_DEFINED(ATSAM4LS4C) \ + ) + +#define SAM4LC ( \ + SAM_PART_IS_DEFINED(ATSAM4LC2A) || \ + SAM_PART_IS_DEFINED(ATSAM4LC2B) || \ + SAM_PART_IS_DEFINED(ATSAM4LC2C) || \ + SAM_PART_IS_DEFINED(ATSAM4LC4A) || \ + SAM_PART_IS_DEFINED(ATSAM4LC4B) || \ + SAM_PART_IS_DEFINED(ATSAM4LC4C) \ + ) +/** @} */ + +/** + * \name SAM families + * @{ + */ +/** SAM3S Family */ +#define SAM3S (SAM3S1 || SAM3S2 || SAM3S4 || SAM3S8 || SAM3SD8) + +/** SAM3U Family */ +#define SAM3U (SAM3U1 || SAM3U2 || SAM3U4) + +/** SAM3N Family */ +#define SAM3N (SAM3N1 || SAM3N2 || SAM3N4) + +/** SAM3XA Family */ +#define SAM3XA (SAM3X4 || SAM3X8 || SAM3A4 || SAM3A8) + +/** SAM4S Family */ +#define SAM4S (SAM4S8 || SAM4S16) + +/** SAM4L Family */ +#define SAM4L (SAM4LS || SAM4LC) +/** @} */ + +/** SAM product line */ +#define SAM (SAM3S || SAM3U || SAM3N || SAM3XA || SAM4S || SAM4L) + +/** @} */ + +/** @} */ + +#endif /* ATMEL_PARTS_H */ diff --git a/DSTAT1/src/asf/xmega/drivers/dma/dma.c b/DSTAT1/src/asf/xmega/drivers/dma/dma.c new file mode 100644 index 0000000..9e7bcc0 --- /dev/null +++ b/DSTAT1/src/asf/xmega/drivers/dma/dma.c @@ -0,0 +1,280 @@ +/** + * \file + * + * \brief AVR XMEGA Direct Memory Access Controller driver + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#include +#include +#include +#include +#include + +/** + * \private + * \brief DMA private data struct + */ +struct dma_data_struct { + /** Callback on complete */ + dma_callback_t callback; +}; + +/** + * \internal + * \brief DMA private data for each channel + */ +struct dma_data_struct dma_data[DMA_NUMBER_OF_CHANNELS]; + +/** + * \brief Enable DMA controller + * + * \note This function will do a soft reset of the DMA controller, clearing all + * previous configuration. + */ +void dma_enable(void) +{ + sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_DMA); + sleepmgr_lock_mode(SLEEPMGR_IDLE); + + /* Reset DMA controller just to make sure everything is from scratch */ + DMA.CTRL = DMA_RESET_bm; + DMA.CTRL = DMA_ENABLE_bm; +} + +/** + * \brief Disable DMA controller + */ +void dma_disable(void) +{ + DMA.CTRL = 0; + sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_DMA); + sleepmgr_unlock_mode(SLEEPMGR_IDLE); +} + +/** + * \brief Set callback for given DMA channel + * + * \param num \ref dma_channel_num_t + * \param callback \ref dma_callback_t + */ +void dma_set_callback(dma_channel_num_t num, dma_callback_t callback) +{ + dma_data[num].callback = callback; +} + +/** + * \internal + * \brief Common DMA channel interrupt handler + * + * Calls the channel callback with the channel status code. The following + * status codes are possible: + * - DMA_CH_TRANSFER_COMPLETED: Transfer completed successfully + * - DMA_CH_TRANSFER_ERROR: Fault in transfer + * + * The optional callback used by the interrupt handler is set by the + * dma_set_callback() function. + * + * \param num DMA channel number to handle interrupt for + */ +static void dma_interrupt(const dma_channel_num_t num) +{ + enum dma_channel_status status; + DMA_CH_t *channel; + + channel = dma_get_channel_address_from_num(num); + status = dma_get_channel_status(num); + + /* Clear all interrupt flags to be sure */ + channel->CTRLB |= DMA_CH_TRNIF_bm | DMA_CH_ERRIF_bm; + + if (dma_data[num].callback) { + dma_data[num].callback(status); + } +} + +/** + * \internal + * \brief DMA channel 0 interrupt handler + */ +ISR(DMA_CH0_vect) +{ + dma_interrupt(0); +} + +#if DMA_NUMBER_OF_CHANNELS > 1 +/** + * \internal + * \brief DMA channel 1 interrupt handler + */ +ISR(DMA_CH1_vect) +{ + dma_interrupt(1); +} +#endif + +#if DMA_NUMBER_OF_CHANNELS > 2 +/** + * \internal + * \brief DMA channel 2 interrupt handler + */ +ISR(DMA_CH2_vect) +{ + dma_interrupt(2); +} +#endif + +#if DMA_NUMBER_OF_CHANNELS > 3 +/** + * \internal + * \brief DMA channel 3 interrupt handler + */ +ISR(DMA_CH3_vect) +{ + dma_interrupt(3); +} +#endif + +/** + * \brief Write DMA channel configuration to hardware + * + * This function will write the DMA channel configuration, provided by a + * \ref dma_channel_config. + * + * \param num DMA channel number to write configuration to + * \param config Pointer to a DMA channel config, given by a + * \ref dma_channel_config + */ +void dma_channel_write_config(dma_channel_num_t num, + struct dma_channel_config *config) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + irqflags_t iflags = cpu_irq_save(); + +#ifdef CONFIG_HAVE_HUGEMEM + channel->DESTADDR0 = (uint32_t)config->destaddr; + channel->DESTADDR1 = (uint32_t)config->destaddr >> 8; + channel->DESTADDR2 = (uint32_t)config->destaddr >> 16; +#else + channel->DESTADDR0 = (uint32_t)config->destaddr16; + channel->DESTADDR1 = (uint32_t)config->destaddr16 >> 8; +# if XMEGA_A || XMEGA_AU + channel->DESTADDR2 = 0; +# endif +#endif + +#ifdef CONFIG_HAVE_HUGEMEM + channel->SRCADDR0 = (uint32_t)config->srcaddr; + channel->SRCADDR1 = (uint32_t)config->srcaddr >> 8; + channel->SRCADDR2 = (uint32_t)config->srcaddr >> 16; +#else + channel->SRCADDR0 = (uint32_t)config->srcaddr16; + channel->SRCADDR1 = (uint32_t)config->srcaddr16 >> 8; +# if XMEGA_A || XMEGA_AU + channel->SRCADDR2 = 0; +# endif +#endif + + channel->ADDRCTRL = config->addrctrl; + channel->TRIGSRC = config->trigsrc; + channel->TRFCNT = config->trfcnt; + channel->REPCNT = config->repcnt; + + channel->CTRLB = config->ctrlb; + + /* Make sure the DMA channel is not enabled before dma_channel_enable() + * is called. + */ +#if XMEGA_A || XMEGA_AU + channel->CTRLA = config->ctrla & ~DMA_CH_ENABLE_bm; +#else + channel->CTRLA = config->ctrla & ~DMA_CH_CHEN_bm; +#endif + + cpu_irq_restore(iflags); +} + +/** + * \brief Read DMA channel configuration from hardware + * + * This function will read the DMA channel configuration into a + * \ref dma_channel_config. + * + * \param num DMA channel number to read configuration from + * \param config Pointer to a DMA channel config, given by a + * \ref dma_channel_config + */ +void dma_channel_read_config(dma_channel_num_t num, + struct dma_channel_config *config) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + irqflags_t iflags = cpu_irq_save(); +#ifdef CONFIG_HAVE_HUGEMEM + uint32_t address; +#else + uint16_t address; +#endif + + address = channel->DESTADDR0; + address |= channel->DESTADDR1 << 8; +#ifdef CONFIG_HAVE_HUGEMEM + address |= (uint32_t)channel->DESTADDR2 << 16; + config->destaddr = (hugemem_ptr_t)address; +#else + config->destaddr16 = address; +#endif + + address = channel->SRCADDR0; + address |= channel->SRCADDR1 << 8; +#ifdef CONFIG_HAVE_HUGEMEM + address |= (uint32_t)channel->SRCADDR2 << 16; + config->srcaddr = (hugemem_ptr_t)address; +#else + config->srcaddr16 = address; +#endif + + config->addrctrl = channel->ADDRCTRL; + config->trigsrc = channel->TRIGSRC; + config->trfcnt = channel->TRFCNT; + config->repcnt = channel->REPCNT; + + config->ctrlb = channel->CTRLB; + config->ctrla = channel->CTRLA; + + cpu_irq_restore(iflags); +} diff --git a/DSTAT1/src/asf/xmega/drivers/dma/dma.h b/DSTAT1/src/asf/xmega/drivers/dma/dma.h new file mode 100644 index 0000000..4e871fd --- /dev/null +++ b/DSTAT1/src/asf/xmega/drivers/dma/dma.h @@ -0,0 +1,1394 @@ +/** + * \file + * + * \brief AVR XMEGA Direct Memory Access Controller driver definitions + * + * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +#ifndef DRIVERS_DMA_DMA_H +#define DRIVERS_DMA_DMA_H + +#include +#include +#include +#include + +/** + * \defgroup dma_group Direct Memory Access controller (DMA) + * + * See \ref xmega_dma_quickstart. + * + * This is a driver for configuration, enabling, disabling and use of the + * on-chip XMEGA Direct Memory Access (DMA) controller. + * + * \section dependencies Dependencies + * + * The direct memory access controller depends on the following modules: + * - \ref pmic_group for setting interrupt level. + * - \ref sysclk_group for peripheral clock control. + * - \ref sleepmgr_group for setting available sleep mode. + * + * @{ + */ + +#if XMEGA_A || XMEGA_AU +# define DMA_NUMBER_OF_CHANNELS 4 +#else +/** Number of available DMA channels, device dependent. */ +# define DMA_NUMBER_OF_CHANNELS 2 +#endif + +/** + * \private + * \brief Helper macro to get the channel offset given the channel number + * + * \param num DMA channel number + * + * \return DMA_CH_t pointer to the \a num DMA channel register struct + */ +#define dma_get_channel_address_from_num(num) \ + ((DMA_CH_t *)((uintptr_t)(&DMA.CH0) + (sizeof(DMA_CH_t) * num))) + +/** \brief DMA channel number type */ +typedef uint8_t dma_channel_num_t; + +/** \brief DMA channel status */ +enum dma_channel_status { + /** DMA channel is idling */ + DMA_CH_FREE = 0, + /** DMA channel has a block transfer pending */ + DMA_CH_PENDING, + /** DMA channel is busy doing a block transfer */ + DMA_CH_BUSY, + /** DMA channel has completed a block transfer */ + DMA_CH_TRANSFER_COMPLETED, + /** DMA channel failed to complete a block transfer */ + DMA_CH_TRANSFER_ERROR, +}; + +/** + * \brief DMA channel configuration struct + */ +struct dma_channel_config { + /** DMA channel control register A */ + uint8_t ctrla; + /** DMA channel control register B */ + uint8_t ctrlb; + /** DMA channel address control register */ + uint8_t addrctrl; + /** DMA channel trigger control register */ + uint8_t trigsrc; + /** DMA channel block transfer count register */ + uint16_t trfcnt; + /** DMA channel repeat counter register */ + uint8_t repcnt; + union { +#ifdef CONFIG_HAVE_HUGEMEM + /** DMA channel source hugemem address */ + hugemem_ptr_t srcaddr; +#endif + /** DMA channel source 16-bit address */ + uint16_t srcaddr16; + }; + union { +#ifdef CONFIG_HAVE_HUGEMEM + /** DMA channel destination hugemem address */ + hugemem_ptr_t destaddr; +#endif + /** DMA channel destaddr 16-bit address */ + uint16_t destaddr16; + }; +}; + +/** DMA interrupt levels */ +enum dma_int_level_t { + DMA_INT_LVL_OFF = 0x00, + DMA_INT_LVL_LO = 0x01, + DMA_INT_LVL_MED = 0x02, + DMA_INT_LVL_HI = 0x03, +}; + +void dma_enable(void); +void dma_disable(void); + +/** \name DMA Controller Management */ +/* @{ */ + +/** + * \brief Set DMA channel priority mode + * + * This functions sets the channel priority mode. Users can select between + * fixed priority, round-robin or a mix of both. + * + * The modes are defined in the toolchain header files in the form of \a + * DMA_PRIMODE_*_gc for devices with more than 2 channels, or DMA_PRIMODE_*_bm + * for dual channel devices. + * + * \param primode DMA channel priority mode given by a DMA_PRIMODE_t type + */ +static inline void dma_set_priority_mode(DMA_PRIMODE_t primode) +{ + irqflags_t iflags; + +#if XMEGA_A || XMEGA_AU + Assert(!(primode & ~DMA_PRIMODE_gm)); +#else + Assert(!(primode & ~DMA_PRIMODE_bm)); +#endif + + iflags = cpu_irq_save(); + +#if XMEGA_A || XMEGA_AU + DMA.CTRL = (DMA.CTRL & ~DMA_PRIMODE_gm) | primode; +#else + DMA.CTRL = (DMA.CTRL & ~DMA_PRIMODE_bm) | primode; +#endif + + cpu_irq_restore(iflags); +} + +/** + * \brief Set DMA channel double buffering mode + * + * This function modifies which channels should be in double buffer mode. The + * modes are defined in the toolchain header files in the form of \a + * DMA_DBUFMODE_*_gc for devices with more than 2 channels, or DMA_DBUFMODE_*_bm + * for dual channel devices. + * + * \param dbufmode Double buffer channel configuration given by a + * DMA_DBUFMODE_t type + */ +static inline void dma_set_double_buffer_mode(DMA_DBUFMODE_t dbufmode) +{ + irqflags_t iflags; + +#if XMEGA_A || XMEGA_AU + Assert(!(dbufmode & ~DMA_DBUFMODE_gm)); +#else + Assert(!(dbufmode & ~DMA_DBUFMODE_bm)); +#endif + + iflags = cpu_irq_save(); + +#if XMEGA_A || XMEGA_AU + DMA.CTRL = (DMA.CTRL & ~DMA_DBUFMODE_gm) | dbufmode; +#else + DMA.CTRL = (DMA.CTRL & ~DMA_DBUFMODE_bm) | dbufmode; +#endif + + cpu_irq_restore(iflags); +} + +/** @} */ + +/** \name DMA Channel Management */ +/** @{ */ + +void dma_channel_write_config(dma_channel_num_t num, + struct dma_channel_config *config); +void dma_channel_read_config(dma_channel_num_t num, + struct dma_channel_config *config); + +/** + * \brief Enable a DMA channel + * + * This function enables a DMA channel, depending on the configuration the DMA + * channel will start the block transfer upon a + * \ref dma_channel_trigger_block_transfer() or when other hardware modules trigger + * the DMA hardware. + * + * \pre The DMA channel configuration must be written to the channel before + * enabling the channel. + * + * \param num DMA channel to enable + */ +static inline void dma_channel_enable(dma_channel_num_t num) +{ + irqflags_t iflags = cpu_irq_save(); + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + +#if XMEGA_A || XMEGA_AU + channel->CTRLA |= DMA_CH_ENABLE_bm; +#else + channel->CTRLA |= DMA_CH_CHEN_bm; +#endif + + cpu_irq_restore(iflags); +} + +/** + * \brief Disable a DMA channel + * + * This function disables a DMA channel. If the DMA channel was already enabled + * the DMA channel is not disabled before the internal transfer buffer is empty + * and the DMA transfer is aborted. + * + * \param num DMA channel to disable + */ +static inline void dma_channel_disable(dma_channel_num_t num) +{ + irqflags_t iflags = cpu_irq_save(); + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + +#if XMEGA_A || XMEGA_AU + channel->CTRLA &= ~DMA_CH_ENABLE_bm; +#else + channel->CTRLA &= ~DMA_CH_CHEN_bm; +#endif + + cpu_irq_restore(iflags); +} + +/** + * \brief Check if DMA channel is enabled + * + * This function checks if a DMA channel is enabled. + * + * \param num DMA channel number to query + * + * \retval true DMA channel is enabled + * \retval false DMA channel is disabled + */ +static inline bool dma_channel_is_enabled(dma_channel_num_t num) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + bool channel_enabled; + +#if XMEGA_A || XMEGA_AU + channel_enabled = (channel->CTRLA & DMA_CH_ENABLE_bm); +#else + channel_enabled = (channel->CTRLA & DMA_CH_CHEN_bm); +#endif + + return channel_enabled; +} + +/** + * \brief Check if DMA channel is busy + * + * This function checks if a DMA channel is busy doing or going to do (pending) + * a block transfer. + * + * \param num DMA channel number to query + * + * \retval true DMA channel is busy or have a block transfer pending + * \retval false DMA channel is not busy or have a block transfer pending + */ +static inline bool dma_channel_is_busy(dma_channel_num_t num) +{ + uint8_t busy_pending = DMA.STATUS; + + busy_pending &= (1 << num) | (1 << (num + 4)); + if (busy_pending) { + return true; + } + + return false; +} + +/** + * \brief Get channel status + * + * This function returns the current channel status. + * + * \param num DMA channel number + * + * \return Channel status given by a \ref dma_channel_status + */ +static inline enum dma_channel_status dma_get_channel_status( + dma_channel_num_t num) +{ + uint8_t busy_pending = DMA.STATUS; + uint8_t error_completed = DMA.INTFLAGS; + + /* + * Check lower and upper nibble of INTFLAGS register to find possible + * error or transfer completed status. + */ + error_completed &= (1 << num) | (1 << (num + 4)); + if (error_completed & (1 << (num + 4))) { + return DMA_CH_TRANSFER_ERROR; + } else if (error_completed & (1 << num)) { + return DMA_CH_TRANSFER_COMPLETED; + } + + /* + * Check lower and upper nibble of STATUS register to find possible + * busy or pending completed status. + */ + busy_pending &= (1 << num) | (1 << (num + 4)); + if (busy_pending & (1 << (num + 4))) { + return DMA_CH_BUSY; + } else if (busy_pending & (1 << num)) { + return DMA_CH_PENDING; + } + + return DMA_CH_FREE; +} + +/** + * \brief DMA channel trigger block transfer + * + * This function triggers a start of a block transfer on a given DMA channel. + * + * \pre The DMA channel must be configured and enabled for this to have any + * affect. + * + * \param num DMA channel number to trigger block transfer for + */ +static inline void dma_channel_trigger_block_transfer(dma_channel_num_t num) +{ + irqflags_t iflags = cpu_irq_save(); + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + + channel->CTRLA |= DMA_CH_TRFREQ_bm; + + cpu_irq_restore(iflags); +} + +/** + * \brief Reset a DMA channel + * + * This function resets a given DMA channel. + * + * \param num DMA channel number to trigger block transfer for + */ +static inline void dma_channel_reset(dma_channel_num_t num) +{ + irqflags_t iflags = cpu_irq_save(); + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + +#if XMEGA_A || XMEGA_AU + channel->CTRLA |= DMA_CH_RESET_bm; +#else + channel->CTRLA |= DMA_CH_CHRST_bm; +#endif + + cpu_irq_restore(iflags); +} + +/** + * \brief Callback definition for DMA channel interrupts + * + * \param status Status of DMA channel block transfer + */ +typedef void (*dma_callback_t)(enum dma_channel_status status); + +void dma_set_callback(dma_channel_num_t num, dma_callback_t callback); + +/** @} */ + +/** + * \name DMA Channel Direct Configuration Functions + * + * These functions allows direct configuration on the DMA channels, not going + * through a \ref dma_channel_config struct. This allows update of the most + * commonly changed DMA channel properties. + * + * @{ + */ + +/** + * \brief Write DMA channel burst length to hardware + * + * This function writes the DMA channel burst length directly to hardware. The + * burst lengths are defined in the toolchain header files in the form of \a + * DMA_CH_BURSTLEN_*_gc, where * represents the various available burst + * lengths. + * + * \param num DMA channel number to write burst length for + * \param burst_length DMA channel burst length given by a DMA_CH_BURSTLEN_t + * type + */ +static inline void dma_channel_write_burst_length(dma_channel_num_t num, + DMA_CH_BURSTLEN_t burst_length) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + irqflags_t iflags = cpu_irq_save(); + + channel->CTRLA &= ~DMA_CH_BURSTLEN_gm; + channel->CTRLA |= burst_length; + + cpu_irq_restore(iflags); +} + +/** + * \brief Write DMA channel transfer count to hardware + * + * This function writes the DMA channel number of bytes in each block transfer + * to hardware. + * + * \param num DMA channel number to write transfer count for + * \param count Number of bytes in each block transfer + */ +static inline void dma_channel_write_transfer_count(dma_channel_num_t num, + uint16_t count) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + irqflags_t iflags = cpu_irq_save(); + + channel->TRFCNT = count; + + cpu_irq_restore(iflags); +} + +/** + * \brief Write DMA channel number of transfer repeats to hardware + * + * This function writes the DMA channel number of block transfer repeats to + * hardware. It will also enable the repeat feature. + * + * \param num DMA channel number to write transfer repeats for + * \param repeats Number of block transfer repeats + */ +static inline void dma_channel_write_repeats(dma_channel_num_t num, + uint8_t repeats) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + irqflags_t iflags = cpu_irq_save(); + + channel->REPCNT = repeats; + channel->CTRLA |= DMA_CH_REPEAT_bm; + + cpu_irq_restore(iflags); +} + +/** + * \brief Write DMA channel 16-bit destination address to hardware + * + * This function writes a DMA channel destination 16-bit LSB address to + *hardware. + * + * \param num DMA channel number to write 16-bit destination address for + * \param destination 16-bit LSB destination address + */ +static inline void dma_channel_write_destination(dma_channel_num_t num, + uint16_t destination) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + irqflags_t iflags = cpu_irq_save(); + + channel->DESTADDR0 = destination; + channel->DESTADDR1 = destination >> 8; + +#if XMEGA_A || XMEGA_AU + /* + * Make sure the third byte of the destination address is zero to avoid + * a runaway DMA transfer. + */ + channel->DESTADDR2 = 0; +#endif + + cpu_irq_restore(iflags); +} + +#ifdef CONFIG_HAVE_HUGEMEM + +/** + * \brief Write DMA channel hugemem destination address to hardware + * + * This function writes a DMA channel destination hugemem address to hardware. + * + * \param num DMA channel number to write hugemem destination address for + * \param destination hugemem destination address + */ +static inline void dma_channel_write_destination_hugemem(dma_channel_num_t num, + hugemem_ptr_t destination) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + irqflags_t iflags = cpu_irq_save(); + + channel->DESTADDR0 = (uint32_t)destination; + channel->DESTADDR1 = (uint32_t)destination >> 8; + channel->DESTADDR2 = (uint32_t)destination >> 16; + + cpu_irq_restore(iflags); +} + +#endif + +/** + * \brief Write DMA channel 16-bit source address to hardware + * + * This function writes a DMA channel source 16-bit LSB address to hardware. + * + * \param num DMA channel number to write 16-bit source address for + * \param source 16-bit LSB source address + */ +static inline void dma_channel_write_source(dma_channel_num_t num, + uint16_t source) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + irqflags_t iflags = cpu_irq_save(); + + channel->SRCADDR0 = source; + channel->SRCADDR1 = source >> 8; + +#if XMEGA_A || XMEGA_AU + /* + * Make sure the third byte of the source address is zero to avoid a + * runaway DMA transfer. + */ + channel->SRCADDR2 = 0; +#endif + + cpu_irq_restore(iflags); +} + +#ifdef CONFIG_HAVE_HUGEMEM + +/** + * \brief Write DMA channel hugemem source address to hardware + * + * This function writes a DMA channel source hugemem address to hardware. + * + * \param num DMA channel number to write hugemem source address for + * \param source hugemem source address + */ +static inline void dma_channel_write_source_hugemem(dma_channel_num_t num, + hugemem_ptr_t source) +{ + DMA_CH_t *channel = dma_get_channel_address_from_num(num); + irqflags_t iflags = cpu_irq_save(); + + channel->SRCADDR0 = (uint32_t)source; + channel->SRCADDR1 = (uint32_t)source >> 8; + channel->SRCADDR2 = (uint32_t)source >> 16; + + cpu_irq_restore(iflags); +} + +#endif + +/** @} */ + +/** \name DMA Channel Configuration Helper Functions */ +/** @{ */ + +/** + * \brief Set DMA channel burst length + * + * This function helps the caller setting the DMA channel burst length. The + * burst lengths are defined in the toolchain header files in the form of \a + * DMA_CH_BURSTLEN_*_gc, where * represents the various available burst + * lengths. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param burst_length DMA channel burst length given by a DMA_CH_BURSTLEN_t + * type + */ +static inline void dma_channel_set_burst_length( + struct dma_channel_config *config, + DMA_CH_BURSTLEN_t burst_length) +{ + config->ctrla &= ~DMA_CH_BURSTLEN_gm; + config->ctrla |= burst_length; +} + +/** + * \brief Set DMA channel in single shot transfer mode + * + * This function helps the caller setting the DMA channel in single shot + * transfer mode. + * + * \param config Pointer to a \ref dma_channel_config variable + */ +static inline void dma_channel_set_single_shot(struct dma_channel_config *config) +{ + config->ctrla |= DMA_CH_SINGLE_bm; +} + +/** + * \brief Unset DMA channel from single shot transfer mode + * + * This function helps the caller clear the DMA channel single shot transfer + * mode feature. + * + * \param config Pointer to a \ref dma_channel_config variable + */ +static inline void dma_channel_unset_single_shot( + struct dma_channel_config *config) +{ + config->ctrla &= ~DMA_CH_SINGLE_bm; +} + +/** + * \brief Set DMA channel interrupt level + * + * This function helps the caller setting the DMA channel interrupt level for + * transaction complete and channel error. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param level Interrupt level given by a \ref dma_int_level_t type + */ +static inline void dma_channel_set_interrupt_level(struct dma_channel_config + *config, enum dma_int_level_t level) +{ + config->ctrlb &= ~(DMA_CH_ERRINTLVL_gm | DMA_CH_TRNINTLVL_gm); + config->ctrlb |= (level << DMA_CH_ERRINTLVL_gp) + | (level << DMA_CH_TRNINTLVL_gp); +} + +/** + * \brief Set DMA channel source address reload mode + * + * This function helps the caller setting the DMA channel source address reload + * mode. The reload modes are defined in the toolchain header files in the form + * of \a DMA_CH_SRCRELOAD_*_gc, where * is NONE, BLOCK, BURST, TRANSACTION. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param mode DMA channel source address reload mode given by an + * DMA_CH_SRCRELOAD_t type + */ +static inline void dma_channel_set_src_reload_mode( + struct dma_channel_config *config, + DMA_CH_SRCRELOAD_t mode) +{ + config->addrctrl &= ~DMA_CH_SRCRELOAD_gm; + config->addrctrl |= mode; +} + +/** + * \brief Set DMA channel destination address reload mode + * + * This function helps the caller setting the DMA channel destination address + * reload mode. The reload modes are defined in the toolchain header files in + * the form of \a DMA_CH_DESTRELOAD_*_gc, where * is NONE, BLOCK, BURST, + * TRANSACTION. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param mode DMA channel destination address reload mode given by an + * DMA_CH_DESTRELOAD_t type + */ +static inline void dma_channel_set_dest_reload_mode( + struct dma_channel_config *config, + DMA_CH_DESTRELOAD_t mode) +{ + config->addrctrl &= ~DMA_CH_DESTRELOAD_gm; + config->addrctrl |= mode; +} + +/** + * \brief Set DMA channel source addressing mode + * + * This function helps the caller setting the DMA channel source addressing + * mode. The addressing modes are defined in the toolchain header files in the + * form of \a DMA_CH_SRCDIR_*_gc, where * is FIXED, INC, DEC. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param mode DMA channel source addressing mode given by an + * DMA_CH_SRCDIR_t type + */ +static inline void dma_channel_set_src_dir_mode( + struct dma_channel_config *config, + DMA_CH_SRCDIR_t mode) +{ + config->addrctrl &= ~DMA_CH_SRCDIR_gm; + config->addrctrl |= mode; +} + +/** + * \brief Set DMA channel destination addressing mode + * + * This function helps the caller setting the DMA channel destination + * addressing mode. The reload modes are defined in the toolchain header files + * in the form of \a DMA_CH_DESTDIR_*_gc, where * is FIXED, INC, DEC. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param mode DMA channel destination addressing mode given by an + * DMA_CH_DESTDIR_t type + */ +static inline void dma_channel_set_dest_dir_mode( + struct dma_channel_config *config, + DMA_CH_DESTDIR_t mode) +{ + config->addrctrl &= ~DMA_CH_DESTDIR_gm; + config->addrctrl |= mode; +} + +/** + * \brief Set DMA channel trigger source + * + * This function helps the caller setting the DMA channel trigger source. The + * trigger sources are defined in the toolchain header files in the form of \a + * DMA_CH_TRIGSRC_*_gc, where * represents the various sources. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param source DMA channel trigger source given by a DMA_CH_TRIGSRC_t type + */ +static inline void dma_channel_set_trigger_source( + struct dma_channel_config *config, + DMA_CH_TRIGSRC_t source) +{ + config->trigsrc = source; +} + +/** + * \brief Set DMA channel transfer count + * + * This function helps the caller setting the DMA channel number of bytes in + * each block transfer. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param count Number of bytes in each block transfer + */ +static inline void dma_channel_set_transfer_count( + struct dma_channel_config *config, + uint16_t count) +{ + config->trfcnt = count; +} + +/** + * \brief Set DMA channel number of transfer repeats + * + * This function helps the caller setting the DMA channel number of block + * transfer repeats. It will also enable the repeat feature. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param repeats Number of block transfer repeats + */ +static inline void dma_channel_set_repeats(struct dma_channel_config *config, + uint8_t repeats) +{ + config->ctrla |= DMA_CH_REPEAT_bm; + config->repcnt = repeats; +} + +/** + * \brief Set DMA channel 16-bit destination address + * + * This function helps the caller setting the DMA channel destination 16-bit + * LSB address. + * + * \note This function assumes the \a config was initialized with zeros (static + * or intentionally zeroed). If not zero filled, there might be garbage left in + * the upper byte of the destination address. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param destination 16-bit LSB destination address + */ +static inline void dma_channel_set_destination_address( + struct dma_channel_config *config, + uint16_t destination) +{ + config->destaddr16 = destination; +} + +#ifdef CONFIG_HAVE_HUGEMEM + +/** + * \brief Set DMA channel hugemem destination address + * + * This function helps the caller setting the DMA channel destination address. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param destination Destination address provided by a \ref hugemem_ptr_t type + */ +static inline void dma_channel_set_destination_hugemem( + struct dma_channel_config *config, + hugemem_ptr_t destination) +{ + config->destaddr = destination; +} + +#endif + +/** + * \brief Set DMA channel 16-bit source address + * + * This function helps the caller setting the DMA channel source 16-bit LSB + * address. + * + * \note This function assumes the \a config was initialized with zeros (static + * or intentionally zeroed). If not zero filled, there might be garbage left in + * the upper byte of the source address. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param source 16-bit LSB source address + */ +static inline void dma_channel_set_source_address( + struct dma_channel_config *config, + uint16_t source) +{ + config->srcaddr16 = source; +} + +#ifdef CONFIG_HAVE_HUGEMEM + +/** + * \brief Set DMA channel hugemem source address + * + * This function helps the caller setting the DMA channel source address. + * + * \param config Pointer to a \ref dma_channel_config variable + * \param source Source address provided by a \ref hugemem_ptr_t type + */ +static inline void dma_channel_set_source_hugemem( + struct dma_channel_config *config, + hugemem_ptr_t source) +{ + config->srcaddr = source; +} + +#endif +/** @} */ + +/** @} */ + +/** + * \page xmega_dma_quickstart Quick start guide for the XMEGA DMA driver + * + * This is the quick start guide for the \ref dma_group "DMA driver", with + * step-by-step instructions on how to configure and use the driver in a + * selection of use cases. + * + * The use cases contain several code fragments. The code fragments in the + * steps for setup can be copied into a custom initialization function, while + * the steps for usage can be copied into, e.g., the main application function. + * + * \section dma_use_cases Advanced use cases + * For more advanced use of the DMA driver, see the following use cases: + * - \subpage dma_use_case_1 + * - \subpage dma_use_case_2 + * + * \section dma_basic_use_case Basic use case + * In this basic use case, the DMA is configured for: + * - Burst length: 1 byte + * - Transfer count: 1024 + * - Source: Buffer located in RAM + * - Destination: Buffer located in RAM + * - Source and destination address reload mode: End of transaction + * - Source and destination address direction mode: Increment + * + * In this use case data is copied from the source buffer to the destination + * buffer in 1-byte bursts, until all data in the block is transferred. This + * example is analogus to a memcpy(destination, source, sizeof(source)) + * operation performed in hardware asynchronously to the CPU. + * + * \section dma_basic_use_case_setup Setup steps + * + * \subsection dma_basic_use_case_setup_prereq Prerequisites + * For the setup code of this use case to work, the following must + * be added to the project: + * -# \ref sysclk_group "System Clock Manager Service (sysclk)" + * + * \subsection dma_basic_use_case_setup_setup_code Example code + * Add to application C-file: + * \code + * #define DMA_CHANNEL 0 + * #define DMA_BUFFER_SIZE 1024 + * + * static uint8_t source[DMA_BUFFER_SIZE]; + * static uint8_t destination[DMA_BUFFER_SIZE]; + * + * static void dma_init(void) + * { + * struct dma_channel_config dmach_conf; + * memset(&dmach_conf, 0, sizeof(dmach_conf)); + * + * dma_channel_set_burst_length(&dmach_conf, DMA_CH_BURSTLEN_1BYTE_gc); + * dma_channel_set_transfer_count(&dmach_conf, DMA_BUFFER_SIZE); + * + * dma_channel_set_src_reload_mode(&dmach_conf, + * DMA_CH_SRCRELOAD_TRANSACTION_gc); + * dma_channel_set_dest_reload_mode(&dmach_conf, + * DMA_CH_DESTRELOAD_TRANSACTION_gc); + * + * dma_channel_set_src_dir_mode(&dmach_conf, DMA_CH_SRCDIR_INC_gc); + * dma_channel_set_source_address(&dmach_conf, + * (uint16_t)(uintptr_t)source); + * + * dma_channel_set_dest_dir_mode(&dmach_conf, DMA_CH_DESTDIR_INC_gc); + * dma_channel_set_destination_address(&dmach_conf, + * (uint16_t)(uintptr_t)destination); + * + * dma_enable(); + * + * dma_channel_write_config(DMA_CHANNEL, &dmach_conf); + * dma_channel_enable(DMA_CHANNEL); + * } + * \endcode + * + * Add to \c main(): + * \code + * sysclk_init(); + * dma_init(); + * \endcode + * + * \subsection dma_basic_use_case_setup_flow Workflow + * -# Define the DMA channel that will be used for the transfer for convenience: + * - \code #define DMA_CHANNEL 0 \endcode + * -# Define the array length that will be the used for the source and + * destination buffers located in RAM: + * - \code #define DMA_BUFFER_SIZE 1024 \endcode + * -# Create a pair of global arrays that will hold the source and destination + * data copied by the DMA controller channel when it is triggered: + * - \code + * static uint8_t source[DMA_BUFFER_SIZE]; + * static uint8_t destination[DMA_BUFFER_SIZE]; + * \endcode + * -# Create a function \c dma_init() to intialize the DMA: + * - \code + * static void dma_init(void) + * { + * // ... + * } + * \endcode + * -# Create config struct for DMA channel: + * - \code struct dma_channel_config dmach_conf; \endcode + * -# Make sure the configuration structure is zeroed out to ensure that all + * values are reset to their defaults before writing new values: + * - \code memset(&dmach_conf, 0, sizeof(dmach_conf)); \endcode + * -# Configure the DMA channel for single byte bursts, with a transfer length + * equal to the size of the source and destination buffers: + * - \code + * dma_channel_set_burst_length(&dmach_conf, DMA_CH_BURSTLEN_1BYTE_gc); + * dma_channel_set_transfer_count(&dmach_conf, DMA_BUFFER_SIZE); + * \endcode + * -# Configure the DMA channel to reset the source and destination addresses at + * the end of the complete transaction (i.e. after \c DMA_BUFFER_SIZE bytes + * copied): + * - \code + * dma_channel_set_src_reload_mode(&dmach_conf, DMA_CH_SRCRELOAD_TRANSACTION_gc); + * dma_channel_set_dest_reload_mode(&dmach_conf, DMA_CH_DESTRELOAD_TRANSACTION_gc); + * \endcode + * -# Configure the DMA channel to increment the source and destination + * addresses after each byte transferred: + * - \code + * dma_channel_set_src_dir_mode(&dmach_conf, DMA_CH_SRCDIR_INC_gc); + * dma_channel_set_dest_dir_mode(&dmach_conf, DMA_CH_DESTDIR_INC_gc); + * \endcode + * -# Configure the DMA channel source and destination addresses: + * - \code + * dma_channel_set_source_address(&dmach_conf, (uint16_t)(uintptr_t)source); + * dma_channel_set_destination_address(&dmach_conf, (uint16_t)(uintptr_t)destination); + * \endcode + * -# Enable the DMA module so that channels can be configured in it: + * - \code dma_enable(); \endcode + * \attention Calling dma_enable() will result in a soft-reset of the entire + * DMA module, clearing all channel configurations. If more than one + * DMA channel is to be configured, this function should be called + * only once in the application initialization procedure only. + * -# Write the DMA channel configuration to the DMA and enable it so that + * it can be triggered to start the transfer: + * - \code + * dma_channel_write_config(DMA_CHANNEL, &dmach_conf); + * dma_channel_enable(DMA_CHANNEL); + * \endcode + * -# Initialize the clock system: + * - \code sysclk_init(); \endcode + * -# Call our DMA init function: + * - \code dma_init(); \endcode + * + * \section dma_basic_use_case_usage Usage steps + * + * \subsection dma_basic_use_case_usage_code Example code + * Add to, e.g., main loop in application C-file: + * \code + * dma_channel_trigger_block_transfer(DMA_CHANNEL); + * do {} while (dma_get_channel_status(DMA_CHANNEL) != DMA_CH_TRANSFER_COMPLETED); + * \endcode + * + * \subsection dma_basic_use_case_usage_flow Workflow + * -# Start the DMA transfer: + * - \code dma_channel_trigger_block_transfer(DMA_CHANNEL); \endcode + * -# Wait for the transfer to complete: + * - \code do {} while (dma_get_channel_status(DMA_CHANNEL) != DMA_CH_TRANSFER_COMPLETED); + * \endcode + */ + +/** + * \page dma_use_case_1 Use case #1 - Interrupt for a completed DMA transfer. + * + * This use case shows how to set up an interrupt for when a DMA transfer is + * completed. + * + * In this use case, the DMA is configured for: + * - Interrupt level: Low + * - Burst length: 1 byte + * - Transfer count: 1024 + * - Source: Buffer located in RAM + * - Destination: Buffer located in RAM + * - Source and destination address reload mode: End of transaction + * - Source and destination address direction mode: Increment + * + * In this use case data is copied from the source buffer to the destination + * buffer in 1-byte bursts, until all data in the block is transferred. This + * example is analogus to a memcpy(destination, source, sizeof(source)) + * operation performed in hardware asynchronously to the CPU. + * + * Each time the DMA transfer completes, a user-specified callback function is + * run to notify the user application. + * + * \section dma_use_case_1_setup Setup steps + * + * \subsection dma_basic_use_case_setup_prereq Prerequisites + * For the setup code of this use case to work, the following must + * be added to the project: + * -# \ref sysclk_group "System Clock Manager Service (sysclk)" + * -# \ref sleepmgr_group "Sleep Manager Service" + * -# \ref pmic_group "PMIC Driver" + * + * A \ref dma_callback_t "callback" function, called \c dma_transfer_done, must + * also be provided by the user application: + * \code + * static void dma_transfer_done(enum dma_channel_status status) + * { + * // ... + * } + * \endcode + * + * \subsection dma_use_case_1_setup_code Example code + * Add to application C-file: + * \code + * #define DMA_CHANNEL 0 + * #define DMA_BUFFER_SIZE 1024 + * + * static uint8_t source[DMA_BUFFER_SIZE]; + * static uint8_t destination[DMA_BUFFER_SIZE]; + * + * static void dma_init(void) + * { + * struct dma_channel_config dmach_conf; + * memset(&dmach_conf, 0, sizeof(dmach_conf)); + * + * dma_channel_set_burst_length(&dmach_conf, DMA_CH_BURSTLEN_1BYTE_gc); + * dma_channel_set_transfer_count(&dmach_conf, DMA_BUFFER_SIZE); + * + * dma_channel_set_src_reload_mode(&dmach_conf, + * DMA_CH_SRCRELOAD_TRANSACTION_gc); + * dma_channel_set_dest_reload_mode(&dmach_conf, + * DMA_CH_DESTRELOAD_TRANSACTION_gc); + * + * dma_channel_set_src_dir_mode(&dmach_conf, DMA_CH_SRCDIR_INC_gc); + * dma_channel_set_source_address(&dmach_conf, + * (uint16_t)(uintptr_t)source); + * + * dma_channel_set_dest_dir_mode(&dmach_conf, DMA_CH_DESTDIR_INC_gc); + * dma_channel_set_destination_address(&dmach_conf, + * (uint16_t)(uintptr_t)destination); + * + * dma_enable(); + * + * dma_set_callback(DMA_CHANNEL, dma_transfer_done); + * dma_channel_set_interrupt_level(&config, DMA_INT_LVL_LO); + * + * dma_channel_write_config(DMA_CHANNEL, &dmach_conf); + * dma_channel_enable(DMA_CHANNEL); + * } + * \endcode + * + * Add to \c main(): + * \code + * sysclk_init(); + * pmic_init(); + * sleepmgr_init(); + * dma_init(); + * cpu_irq_enable(); + * \endcode + * + * \subsection dma_use_case_1_setup_flow Workflow + * -# Define the DMA channel that will be used for the transfer for convenience: + * - \code #define DMA_CHANNEL 0 \endcode + * -# Define the array length that will be the used for the source and + * destination buffers located in RAM: + * - \code #define DMA_BUFFER_SIZE 1024 \endcode + * -# Create a pair of global arrays that will hold the source and destination + * data copied by the DMA controller channel when it is triggered: + * - \code + * static uint8_t source[DMA_BUFFER_SIZE]; + * static uint8_t destination[DMA_BUFFER_SIZE]; + * \endcode + * -# Create a function \c dma_init() to intialize the DMA: + * - \code + * static void dma_init(void) + * { + * // ... + * } + * \endcode + * -# Create config struct for DMA channel: + * - \code struct dma_channel_config dmach_conf; \endcode + * -# Make sure the configuration structure is zeroed out to ensure that all + * values are reset to their defaults before writing new values: + * - \code memset(&dmach_conf, 0, sizeof(dmach_conf)); \endcode + * -# Configure the DMA channel for single byte bursts, with a transfer length + * equal to the size of the source and destination buffers: + * - \code + * dma_channel_set_burst_length(&dmach_conf, DMA_CH_BURSTLEN_1BYTE_gc); + * dma_channel_set_transfer_count(&dmach_conf, DMA_BUFFER_SIZE); + * \endcode + * -# Configure the DMA channel to reset the source and destination addresses at + * the end of the complete transaction (i.e. after \c DMA_BUFFER_SIZE bytes + * copied): + * - \code + * dma_channel_set_src_reload_mode(&dmach_conf, DMA_CH_SRCRELOAD_TRANSACTION_gc); + * dma_channel_set_dest_reload_mode(&dmach_conf, DMA_CH_DESTRELOAD_TRANSACTION_gc); + * \endcode + * -# Configure the DMA channel to increment the source and destination + * addresses after each byte transferred: + * - \code + * dma_channel_set_src_dir_mode(&dmach_conf, DMA_CH_SRCDIR_INC_gc); + * dma_channel_set_dest_dir_mode(&dmach_conf, DMA_CH_DESTDIR_INC_gc); + * \endcode + * -# Configure the DMA channel source and destination addresses: + * - \code + * dma_channel_set_source_address(&dmach_conf, (uint16_t)(uintptr_t)source); + * dma_channel_set_destination_address(&dmach_conf, + * (uint16_t)(uintptr_t)destination); + * \endcode + * -# Enable the DMA module so that channels can be configured in it: + * - \code dma_enable(); \endcode + * \attention Calling dma_enable() will result in a soft-reset of the entire + * DMA module, clearing all channel configurations. If more than one + * DMA channel is to be configured, this function should be called + * only once in the application initialization procedure only. + * -# Set up the DMA channel interrupt to run at low interrupt priority, and + * link it to the user created \c dma_transfer_done() function: + * - \code + * dma_set_callback(DMA_CHANNEL, dma_transfer_done); + * dma_channel_set_interrupt_level(&config, DMA_INT_LVL_LO); + * \endcode + * -# Write the DMA channel configuration to the DMA and enable it so that + * it can be triggered to start the transfer: + * - \code + * dma_channel_write_config(DMA_CHANNEL, &dmach_conf); + * dma_channel_enable(DMA_CHANNEL); + * \endcode + * -# Initialize the clock system, PMIC driver and Sleep Manager service: + * - \code + * sysclk_init(); + * pmic_init(); + * sleepmgr_init(); + * \endcode + * -# Call our DMA init function: + * - \code dma_init(); \endcode + * -# Enable global processing of interrupts: + * - \code cpu_irq_enable(); \endcode + * + * \section dma_use_case_1_usage Usage steps + * + * \subsection dma_use_case_1_usage_code Example code + * Add to, e.g., main loop in application C-file: + * \code + * dma_channel_trigger_block_transfer(DMA_CHANNEL); + * sleepmgr_enter_sleep(); + * \endcode + * + * \subsection dma_use_case_1_usage_flow Workflow + * -# Start the DMA transfer: + * - \code dma_channel_trigger_block_transfer(DMA_CHANNEL); \endcode + * -# Sleep while waiting for the transfer to complete: + * - \code sleepmgr_enter_sleep(); \endcode + */ + +/** + * \page dma_use_case_2 Use case #2 - Event driven DMA transfer from a peripheral. + * + * This use case shows how to set up a burst DMA transfer between a peripheral + * register set and the main system memory. + * + * In this use case, the DMA is configured for: + * - Burst length: 2 bytes (one 16-bit result from the ADC peripheral) + * - Transfer count: 1024 (512 16-bit samples) + * - Source: ADC channel 0 result register + * - Destination: Buffer located in RAM + * - Source address reload mode: End of burst + * - Destination address reload mode: End of transaction + * - Source and destination address direction mode: Increment + * + * In this use case data is copied from the 16-bit ADC channel 0 result register + * to a buffer in RAM, each time the ADC indicates that a new conversion has + * completed. + * + * \section dma_use_case_2_setup Setup steps + * + * \subsection dma_basic_use_case_setup_prereq Prerequisites + * For the setup code of this use case to work, the following must + * be added to the project: + * -# \ref sysclk_group "System Clock Manager Service (sysclk)" + * + * The ADC must be configured according to the XMEGA ADC driver Quick Start + * \ref adc_basic_use_case "basic use case". + * + * \subsection dma_use_case_2_setup_code Example code + * Add to application C-file: + * \code + * #define DMA_CHANNEL 0 + * #define DMA_BUFFER_SIZE 1024 + * + * static uint16_t adc_samples[DMA_BUFFER_SIZE / 2]; + * + * static void dma_init(void) + * { + * struct dma_channel_config dmach_conf; + * memset(&dmach_conf, 0, sizeof(dmach_conf)); + * + * dma_channel_set_burst_length(&dmach_conf, DMA_CH_BURSTLEN_2BYTE_gc); + * dma_channel_set_transfer_count(&dmach_conf, DMA_BUFFER_SIZE); + * + * dma_channel_set_src_reload_mode(&dmach_conf, + * DMA_CH_SRCRELOAD_BURST_gc); + * dma_channel_set_dest_reload_mode(&dmach_conf, + * DMA_CH_DESTRELOAD_TRANSACTION_gc); + * + * dma_channel_set_src_dir_mode(&dmach_conf, DMA_CH_SRCDIR_INC_gc); + * dma_channel_set_dest_dir_mode(&dmach_conf, DMA_CH_DESTDIR_INC_gc); + * + * dma_channel_set_source_address(&dmach_conf, + * (uint16_t)(uintptr_t)&ADCA.CH0RES); + * dma_channel_set_destination_address(&dmach_conf, + * (uint16_t)(uintptr_t)adc_samples); + * + * dma_channel_set_trigger_source(&dmach_conf, DMA_CH_TRIGSRC_ADCA_CH0_gc); + * dma_channel_set_single_shot(&dmach_conf); + * + * dma_enable(); + * + * dma_set_callback(DMA_CHANNEL, dma_transfer_done); + * dma_channel_set_interrupt_level(&config, DMA_INT_LVL_LO); + * + * dma_channel_write_config(DMA_CHANNEL, &dmach_conf); + * dma_channel_enable(DMA_CHANNEL); + * } + * \endcode + * + * Add to \c main(): + * \code + * sysclk_init(); + * dma_init(); + * \endcode + * + * \subsection dma_use_case_2_setup_flow Workflow + * -# Define the DMA channel that will be used for the transfer for convenience: + * - \code #define DMA_CHANNEL 0 \endcode + * -# Define the array length that will be the used for the source and + * destination buffers located in RAM: + * - \code #define DMA_BUFFER_SIZE 1024 \endcode + * -# Create a global array that will hold the ADC sample result data copied by + * the DMA controller channel when it is triggered (the buffer size is + * halved as each sample is two bytes long): + * - \code static uint16_t adc_samples[DMA_BUFFER_SIZE / 2]; \endcode + * -# Create a function \c dma_init() to intialize the DMA: + * - \code + * static void dma_init(void) + * { + * // ... + * } + * \endcode + * -# Create config struct for DMA channel: + * - \code struct dma_channel_config dmach_conf; \endcode + * -# Make sure the configuration structure is zeroed out to ensure that all + * values are reset to their defaults before writing new values: + * - \code memset(&dmach_conf, 0, sizeof(dmach_conf)); \endcode + * -# Configure the DMA channel for two byte bursts (the size of a single ADC + * conversion) with a transfer length equal to the size of the destination + * buffer: + * - \code + * dma_channel_set_burst_length(&dmach_conf, DMA_CH_BURSTLEN_2BYTE_gc); + * dma_channel_set_transfer_count(&dmach_conf, DMA_BUFFER_SIZE); + * \endcode + * -# Configure the DMA channel to reset the source address at the end of each + * burst transfer, and the destination addresses at the end of the complete + * transaction (i.e. after \c DMA_BUFFER_SIZE bytes copied): + * - \code + * dma_channel_set_src_reload_mode(&dmach_conf, DMA_CH_SRCRELOAD_BURST_gc); + * dma_channel_set_dest_reload_mode(&dmach_conf, DMA_CH_DESTRELOAD_TRANSACTION_gc); + * \endcode + * -# Configure the DMA channel to increment the source and destination + * addresses after each byte transferred: + * - \code + * dma_channel_set_src_dir_mode(&dmach_conf, DMA_CH_SRCDIR_INC_gc); + * dma_channel_set_dest_dir_mode(&dmach_conf, DMA_CH_DESTDIR_INC_gc); + * \endcode + * -# Configure the DMA channel source and destination addresses to the ADC + * module channel 0 result registers and RAM buffer respectively: + * - \code + * dma_channel_set_source_address(&dmach_conf, + * (uint16_t)(uintptr_t)&ADCA.CH0RES); + * dma_channel_set_destination_address(&dmach_conf, + * (uint16_t)(uintptr_t)adc_samples); + * \endcode + * -# Set the DMA channel trigger source to the ADC module channel 0 complete + * event: + * - \code dma_channel_set_trigger_source(&dmach_conf, DMA_CH_TRIGSRC_ADCA_CH0_gc); \endcode + * -# Configure the DMA channel in single shot mode, so that each time it is + * triggered it will perform one bust transfer only: + * - \code dma_channel_set_single_shot(&dmach_conf); \endcode + * -# Enable the DMA module so that channels can be configured in it: + * - \code dma_enable(); \endcode + * \attention Calling dma_enable() will result in a soft-reset of the entire + * DMA module, clearing all channel configurations. If more than one + * DMA channel is to be configured, this function should be called + * only once in the application initialization procedure only. + * -# Set up the DMA channel interrupt to run at low interrupt priority, and + * link it to the user created \c dma_transfer_done() function: + * - \code + * dma_set_callback(DMA_CHANNEL, dma_transfer_done); + * dma_channel_set_interrupt_level(&config, DMA_INT_LVL_LO); + * \endcode + * -# Write the DMA channel configuration to the DMA and enable it so that + * it can be triggered to start the transfer: + * - \code + * dma_channel_write_config(DMA_CHANNEL, &dmach_conf); + * dma_channel_enable(DMA_CHANNEL); + * \endcode + * -# Initialize the clock system: + * - \code sysclk_init(); \endcode + * -# Call our DMA init function: + * - \code dma_init(); \endcode + * + * \section dma_use_case_2_usage Usage steps + * + * \subsection dma_use_case_2_usage_code Example code + * Add to, e.g., main loop in application C-file: + * \code + * adc_start_conversion(&ADCA, ADC_CH0); + * adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); + * \endcode + * + * \subsection dma_use_case_2_usage_flow Workflow + * -# Start an ADC conversion, result will be automatically copied to the + * global buffer when complete: + * - \code adc_start_conversion(&ADCA, ADC_CH0); \endcode + * -# Wait for the ADC to complete before triggering the next conversion by + * polling the ADC channel 0 complete interrupt flag: + * - \code adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); \endcode + */ + +#endif /* DRIVERS_DMA_DMA_H */ diff --git a/DSTAT1/src/main.h b/DSTAT1/src/main.h index 9fb8485..c347318 100644 --- a/DSTAT1/src/main.h +++ b/DSTAT1/src/main.h @@ -5,10 +5,6 @@ * Author: mdryden */ -// #include -// #include - - int8_t autogainswitch(void); void menu(uint8_t selection); -- GitLab